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