1""" 2Test thread creation after process attach. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9from lldbsuite.test import lldbutil 10 11 12class CreateAfterAttachTestCase(TestBase): 13 def setUp(self): 14 # Call super's setUp(). 15 TestBase.setUp(self) 16 # Find the line numbers for our breakpoints. 17 self.break_1 = line_number("main.cpp", "// Set first breakpoint here") 18 self.break_2 = line_number("main.cpp", "// Set second breakpoint here") 19 self.break_3 = line_number("main.cpp", "// Set third breakpoint here") 20 21 # Occasionally hangs on Windows, may be same as other issues. 22 @skipIfWindows 23 @skipIfiOSSimulator 24 @expectedFailureNetBSD 25 def test_create_after_attach(self): 26 """Test thread creation after process attach.""" 27 self.build() 28 exe = self.getBuildArtifact("a.out") 29 30 # Spawn a new process 31 # use realpath to workaround llvm.org/pr48376 32 popen = self.spawnSubprocess(os.path.realpath(exe)) 33 pid = popen.pid 34 35 # Attach to the spawned process 36 self.runCmd("process attach -p " + str(pid)) 37 38 target = self.dbg.GetSelectedTarget() 39 40 process = target.GetProcess() 41 self.assertTrue(process, PROCESS_IS_VALID) 42 43 # This should create a breakpoint in the main thread. 44 lldbutil.run_break_set_by_file_and_line( 45 self, "main.cpp", self.break_1, num_expected_locations=1 46 ) 47 48 # This should create a breakpoint in the second child thread. 49 lldbutil.run_break_set_by_file_and_line( 50 self, "main.cpp", self.break_2, num_expected_locations=1 51 ) 52 53 # This should create a breakpoint in the first child thread. 54 lldbutil.run_break_set_by_file_and_line( 55 self, "main.cpp", self.break_3, num_expected_locations=1 56 ) 57 58 # Note: With std::thread, we cannot rely on particular thread numbers. Using 59 # std::thread may cause the program to spin up a thread pool (and it does on 60 # Windows), so the thread numbers are non-deterministic. 61 62 # Run to the first breakpoint 63 self.runCmd("continue") 64 65 # The stop reason of the thread should be breakpoint. 66 self.expect( 67 "thread list", 68 STOPPED_DUE_TO_BREAKPOINT, 69 substrs=["stopped", "* thread #", "main", "stop reason = breakpoint"], 70 ) 71 72 # Change a variable to escape the loop 73 self.runCmd("expression main_thread_continue = 1") 74 75 # Run to the second breakpoint 76 self.runCmd("continue") 77 78 # The stop reason of the thread should be breakpoint. 79 self.expect( 80 "thread list", 81 STOPPED_DUE_TO_BREAKPOINT, 82 substrs=[ 83 "stopped", 84 "* thread #", 85 "thread_2_func", 86 "stop reason = breakpoint", 87 ], 88 ) 89 90 # Change a variable to escape the loop 91 self.runCmd("expression child_thread_continue = 1") 92 93 # Run to the third breakpoint 94 self.runCmd("continue") 95 96 # The stop reason of the thread should be breakpoint. 97 # Thread 3 may or may not have already exited. 98 self.expect( 99 "thread list", 100 STOPPED_DUE_TO_BREAKPOINT, 101 substrs=[ 102 "stopped", 103 "* thread #", 104 "thread_1_func", 105 "stop reason = breakpoint", 106 ], 107 ) 108 109 # Run to completion 110 self.runCmd("continue") 111 112 # At this point, the inferior process should have exited. 113 self.assertEqual(process.GetState(), lldb.eStateExited, PROCESS_EXITED) 114