aboutsummaryrefslogtreecommitdiff
path: root/lldb/test/API/python_api
diff options
context:
space:
mode:
authorjimingham <jingham@apple.com>2024-07-15 15:07:01 -0700
committerGitHub <noreply@github.com>2024-07-15 15:07:01 -0700
commit44d9692e6a657ec46e98e4912ac56417da67cfee (patch)
treec0ac2f6077821a294a7f37b9b013988cb9b3882e /lldb/test/API/python_api
parent63b16afc54527d8976571d36b17d85f401e4f6a1 (diff)
downloadllvm-44d9692e6a657ec46e98e4912ac56417da67cfee.zip
llvm-44d9692e6a657ec46e98e4912ac56417da67cfee.tar.gz
llvm-44d9692e6a657ec46e98e4912ac56417da67cfee.tar.bz2
Private process events were being delivered to the secondary listener (#98571)
This fixes a bug where Process events were being delivered to secondary listeners when the Private state thread listener was processing the event. That meant the secondary listener could get an event before the Primary listener did. That in turn meant the state when the secondary listener got the event wasn't right yet. Plus it meant that the secondary listener saw more events than the primary (not all events get forwarded from the private to the public Process listener.) This bug became much more evident when we had a stop hook that did some work, since that delays the Primary listener event delivery. So I also added a stop-hook to the test, and put a little delay in as well.
Diffstat (limited to 'lldb/test/API/python_api')
-rw-r--r--lldb/test/API/python_api/event/TestEvents.py44
1 files changed, 39 insertions, 5 deletions
diff --git a/lldb/test/API/python_api/event/TestEvents.py b/lldb/test/API/python_api/event/TestEvents.py
index d8d3dd2..fb1a7e3 100644
--- a/lldb/test/API/python_api/event/TestEvents.py
+++ b/lldb/test/API/python_api/event/TestEvents.py
@@ -7,7 +7,7 @@ import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-
+import random
@skipIfLinux # llvm.org/pr25924, sometimes generating SIGSEGV
class EventAPITestCase(TestBase):
@@ -20,6 +20,7 @@ class EventAPITestCase(TestBase):
self.line = line_number(
"main.c", '// Find the line number of function "c" here.'
)
+ random.seed()
@expectedFailureAll(
oslist=["linux"], bugnumber="llvm.org/pr23730 Flaky, fails ~1/10 cases"
@@ -318,6 +319,7 @@ class EventAPITestCase(TestBase):
"""Wait for an event from self.primary & self.shadow listener.
If test_shadow is true, we also check that the shadow listener only
receives events AFTER the primary listener does."""
+ import stop_hook
# Waiting on the shadow listener shouldn't have events yet because
# we haven't fetched them for the primary listener yet:
event = lldb.SBEvent()
@@ -328,12 +330,23 @@ class EventAPITestCase(TestBase):
# But there should be an event for the primary listener:
success = self.primary_listener.WaitForEvent(5, event)
+
self.assertTrue(success, "Primary listener got the event")
state = lldb.SBProcess.GetStateFromEvent(event)
+ primary_event_type = event.GetType()
restart = False
if state == lldb.eStateStopped:
restart = lldb.SBProcess.GetRestartedFromEvent(event)
+ # This counter is matching the stop hooks, which don't get run
+ # for auto-restarting stops.
+ if not restart:
+ self.stop_counter += 1
+ self.assertEqual(
+ stop_hook.StopHook.counter[self.instance],
+ self.stop_counter,
+ "matching stop hook",
+ )
if expected_state is not None:
self.assertEqual(
@@ -344,15 +357,18 @@ class EventAPITestCase(TestBase):
# listener:
success = self.shadow_listener.WaitForEvent(5, event)
self.assertTrue(success, "Shadow listener got event too")
+ shadow_event_type = event.GetType()
+ self.assertEqual(
+ primary_event_type, shadow_event_type, "It was the same event type"
+ )
self.assertEqual(
- state, lldb.SBProcess.GetStateFromEvent(event), "It was the same event"
+ state, lldb.SBProcess.GetStateFromEvent(event), "It was the same state"
)
self.assertEqual(
restart,
lldb.SBProcess.GetRestartedFromEvent(event),
"It was the same restarted",
)
-
return state, restart
@expectedFlakeyLinux("llvm.org/pr23730") # Flaky, fails ~1/100 cases
@@ -386,6 +402,20 @@ class EventAPITestCase(TestBase):
)
self.dbg.SetAsync(True)
+ # Now make our stop hook - we want to ensure it stays up to date with
+ # the events. We can't get our hands on the stop-hook instance directly,
+ # so we'll pass in an instance key, and use that to retrieve the data from
+ # this instance of the stop hook:
+ self.instance = f"Key{random.randint(0,10000)}"
+ stop_hook_path = os.path.join(self.getSourceDir(), "stop_hook.py")
+ self.runCmd(f"command script import {stop_hook_path}")
+ import stop_hook
+
+ self.runCmd(
+ f"target stop-hook add -P stop_hook.StopHook -k instance -v {self.instance}"
+ )
+ self.stop_counter = 0
+
self.process = target.Launch(launch_info, error)
self.assertSuccess(error, "Process launched successfully")
@@ -395,6 +425,7 @@ class EventAPITestCase(TestBase):
# Events in the launch sequence might be platform dependent, so don't
# expect any particular event till we get the stopped:
state = lldb.eStateInvalid
+
while state != lldb.eStateStopped:
state, restart = self.wait_for_next_event(None, False)
@@ -412,8 +443,6 @@ class EventAPITestCase(TestBase):
self.cur_thread.GetStopReasonDataAtIndex(0),
"Hit the right breakpoint",
)
- # Disable the first breakpoint so it doesn't get in the way...
- bkpt1.SetEnabled(False)
self.cur_thread.StepOver()
# We'll run the test for "shadow listener blocked by primary listener
@@ -450,4 +479,9 @@ class EventAPITestCase(TestBase):
)
if state == lldb.eStateStopped and not restarted:
self.process.Continue()
+
state, restarted = self.wait_for_next_event(None, False)
+
+ # Now make sure we agree with the stop hook counter:
+ self.assertEqual(self.stop_counter, stop_hook.StopHook.counter[self.instance])
+ self.assertEqual(stop_hook.StopHook.non_stops[self.instance], 0, "No non stops")