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 @skipUnlessDarwin 13 @add_test_categories(["pyapi"]) 14 def test_with_python_api(self): 15 """Test that we get thread names when interrupting a process.""" 16 self.build() 17 exe = self.getBuildArtifact("a.out") 18 19 target = self.dbg.CreateTarget(exe) 20 self.assertTrue(target, VALID_TARGET) 21 22 launch_info = target.GetLaunchInfo() 23 error = lldb.SBError() 24 self.dbg.SetAsync(True) 25 process = target.Launch(launch_info, error) 26 self.assertTrue(process, PROCESS_IS_VALID) 27 28 listener = self.dbg.GetListener() 29 broadcaster = process.GetBroadcaster() 30 rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) 31 self.assertNotEqual(rc, 0, "Unable to add listener to process") 32 self.assertTrue( 33 self.wait_for_running(process, listener), 34 "Check that process is up and running", 35 ) 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.assertEqual(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 # The process will set a global variable 'threads_up_and_running' to 1 when 62 # it has has completed its setup. Sleep for one second, pause the program, 63 # check to see if the global has that value, and continue if it does not. 64 def wait_until_program_setup_complete(self, process, listener): 65 inferior_set_up = lldb.SBValue() 66 retry = 5 67 while retry > 0: 68 arch = self.getArchitecture() 69 # when running the testsuite against a remote arm device, it may take 70 # a little longer for the process to start up. Use a "can't possibly take 71 # longer than this" value. 72 if arch == "arm64" or arch == "armv7": 73 time.sleep(10) 74 else: 75 time.sleep(1) 76 process.SendAsyncInterrupt() 77 self.assertTrue( 78 self.wait_for_stop(process, listener), "Check that process is paused" 79 ) 80 inferior_set_up = process.GetTarget().CreateValueFromExpression( 81 "threads_up_and_running", "threads_up_and_running" 82 ) 83 if inferior_set_up.IsValid() and inferior_set_up.GetValueAsSigned() == 1: 84 retry = 0 85 else: 86 process.Continue() 87 retry = retry - 1 88 return inferior_set_up 89 90 # Listen to the process events until we get an event saying that the process is 91 # running. Retry up to five times in case we get other events that are not 92 # what we're looking for. 93 def wait_for_running(self, process, listener): 94 retry_count = 5 95 if process.GetState() == lldb.eStateRunning: 96 return True 97 98 while retry_count > 0: 99 event = lldb.SBEvent() 100 listener.WaitForEvent(2, event) 101 if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged: 102 if process.GetState() == lldb.eStateRunning: 103 return True 104 retry_count = retry_count - 1 105 106 return False 107 108 # Listen to the process events until we get an event saying the process is 109 # stopped. Retry up to five times in case we get other events that we are 110 # not looking for. 111 def wait_for_stop(self, process, listener): 112 retry_count = 5 113 if ( 114 process.GetState() == lldb.eStateStopped 115 or process.GetState() == lldb.eStateCrashed 116 or process.GetState() == lldb.eStateDetached 117 or process.GetState() == lldb.eStateExited 118 ): 119 return True 120 121 while retry_count > 0: 122 event = lldb.SBEvent() 123 listener.WaitForEvent(2, event) 124 if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged: 125 if ( 126 process.GetState() == lldb.eStateStopped 127 or process.GetState() == lldb.eStateCrashed 128 or process.GetState() == lldb.eStateDetached 129 or process.GetState() == lldb.eStateExited 130 ): 131 return True 132 if ( 133 process.GetState() == lldb.eStateCrashed 134 or process.GetState() == lldb.eStateDetached 135 or process.GetState() == lldb.eStateExited 136 ): 137 return False 138 retry_count = retry_count - 1 139 140 return False 141 142 def check_number_of_threads(self, process): 143 self.assertEqual( 144 process.GetNumThreads(), 145 3, 146 "Check that the process has three threads when sitting at the stopper() breakpoint", 147 ) 148 149 def check_expected_threads_present(self, main_thread, second_thread, third_thread): 150 self.assertTrue( 151 main_thread.IsValid() 152 and second_thread.IsValid() 153 and third_thread.IsValid(), 154 "Got all three expected threads", 155 ) 156