1"""Test that we get thread names when interrupting a process.""" 2 3 4import time 5import lldb 6from lldbsuite.test.decorators import * 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test import lldbutil 9 10 11class TestInterruptThreadNames(TestBase): 12 13 mydir = TestBase.compute_mydir(__file__) 14 15 @skipUnlessDarwin 16 @add_test_categories(['pyapi']) 17 def test_with_python_api(self): 18 """Test that we get thread names when interrupting a process.""" 19 self.build() 20 exe = self.getBuildArtifact("a.out") 21 22 target = self.dbg.CreateTarget(exe) 23 self.assertTrue(target, VALID_TARGET) 24 25 launch_info = target.GetLaunchInfo() 26 error = lldb.SBError() 27 self.dbg.SetAsync(True) 28 process = target.Launch(launch_info, error) 29 self.assertTrue(process, PROCESS_IS_VALID) 30 31 listener = self.dbg.GetListener() 32 broadcaster = process.GetBroadcaster() 33 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) 34 self.assertNotEqual(rc, 0, "Unable to add listener to process") 35 self.assertTrue(self.wait_for_running(process, listener), "Check that process is up and running") 36 37 inferior_set_up = self.wait_until_program_setup_complete(process, listener) 38 39 # Check that the program was able to create its threads within the allotted time 40 self.assertTrue(inferior_set_up.IsValid()) 41 self.assertEquals(inferior_set_up.GetValueAsSigned(), 1) 42 43 self.check_number_of_threads(process) 44 45 main_thread = lldb.SBThread() 46 second_thread = lldb.SBThread() 47 third_thread = lldb.SBThread() 48 for idx in range(0, process.GetNumThreads()): 49 t = process.GetThreadAtIndex(idx) 50 if t.GetName() == "main thread": 51 main_thread = t 52 if t.GetName() == "second thread": 53 second_thread = t 54 if t.GetName() == "third thread": 55 third_thread = t 56 57 self.check_expected_threads_present(main_thread, second_thread, third_thread) 58 59 process.Kill() 60 61 62 # The process will set a global variable 'threads_up_and_running' to 1 when 63 # it has has completed its setup. Sleep for one second, pause the program, 64 # check to see if the global has that value, and continue if it does not. 65 def wait_until_program_setup_complete(self, process, listener): 66 inferior_set_up = lldb.SBValue() 67 retry = 5 68 while retry > 0: 69 arch = self.getArchitecture() 70 # when running the testsuite against a remote arm device, it may take 71 # a little longer for the process to start up. Use a "can't possibly take 72 # longer than this" value. 73 if arch == 'arm64' or arch == 'armv7': 74 time.sleep(10) 75 else: 76 time.sleep(1) 77 process.SendAsyncInterrupt() 78 self.assertTrue(self.wait_for_stop(process, listener), "Check that process is paused") 79 inferior_set_up = process.GetTarget().CreateValueFromExpression("threads_up_and_running", "threads_up_and_running") 80 if inferior_set_up.IsValid() and inferior_set_up.GetValueAsSigned() == 1: 81 retry = 0 82 else: 83 process.Continue() 84 retry = retry - 1 85 return inferior_set_up 86 87 # Listen to the process events until we get an event saying that the process is 88 # running. Retry up to five times in case we get other events that are not 89 # what we're looking for. 90 def wait_for_running(self, process, listener): 91 retry_count = 5 92 if process.GetState() == lldb.eStateRunning: 93 return True 94 95 while retry_count > 0: 96 event = lldb.SBEvent() 97 listener.WaitForEvent(2, event) 98 if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged: 99 if process.GetState() == lldb.eStateRunning: 100 return True 101 retry_count = retry_count - 1 102 103 return False 104 105 # Listen to the process events until we get an event saying the process is 106 # stopped. Retry up to five times in case we get other events that we are 107 # not looking for. 108 def wait_for_stop(self, process, listener): 109 retry_count = 5 110 if process.GetState() == lldb.eStateStopped or process.GetState() == lldb.eStateCrashed or process.GetState() == lldb.eStateDetached or process.GetState() == lldb.eStateExited: 111 return True 112 113 while retry_count > 0: 114 event = lldb.SBEvent() 115 listener.WaitForEvent(2, event) 116 if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged: 117 if process.GetState() == lldb.eStateStopped or process.GetState() == lldb.eStateCrashed or process.GetState() == lldb.eStateDetached or process.GetState() == lldb.eStateExited: 118 return True 119 if process.GetState() == lldb.eStateCrashed or process.GetState() == lldb.eStateDetached or process.GetState() == lldb.eStateExited: 120 return False 121 retry_count = retry_count - 1 122 123 return False 124 125 126 127 def check_number_of_threads(self, process): 128 self.assertEqual( 129 process.GetNumThreads(), 3, 130 "Check that the process has three threads when sitting at the stopper() breakpoint") 131 132 def check_expected_threads_present(self, main_thread, second_thread, third_thread): 133 self.assertTrue( 134 main_thread.IsValid() and second_thread.IsValid() and third_thread.IsValid(), 135 "Got all three expected threads") 136