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