1""" 2Test number of threads. 3""" 4 5 6import lldb 7from lldbsuite.test.decorators import * 8from lldbsuite.test.lldbtest import * 9import lldbsuite.test.lldbutil as lldbutil 10 11 12class NumberOfThreadsTestCase(TestBase): 13 NO_DEBUG_INFO_TESTCASE = True 14 15 def setUp(self): 16 # Call super's setUp(). 17 TestBase.setUp(self) 18 # Find the line numbers for our break points. 19 self.thread3_notify_all_line = line_number( 20 "main.cpp", "// Set thread3 break point on notify_all at this line." 21 ) 22 self.thread3_before_lock_line = line_number( 23 "main.cpp", "// thread3-before-lock" 24 ) 25 26 def test_number_of_threads(self): 27 """Test number of threads.""" 28 self.build() 29 exe = self.getBuildArtifact("a.out") 30 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 31 32 # This should create a breakpoint with 1 location. 33 lldbutil.run_break_set_by_file_and_line( 34 self, "main.cpp", self.thread3_notify_all_line, num_expected_locations=1 35 ) 36 37 # The breakpoint list should show 1 location. 38 self.expect( 39 "breakpoint list -f", 40 "Breakpoint location shown correctly", 41 substrs=[ 42 "1: file = 'main.cpp', line = %d, exact_match = 0, locations = 1" 43 % self.thread3_notify_all_line 44 ], 45 ) 46 47 # Run the program. 48 self.runCmd("run", RUN_SUCCEEDED) 49 50 # Stopped once. 51 self.expect( 52 "thread list", 53 STOPPED_DUE_TO_BREAKPOINT, 54 substrs=["stop reason = breakpoint 1."], 55 ) 56 57 # Get the target process 58 target = self.dbg.GetSelectedTarget() 59 process = target.GetProcess() 60 61 # Get the number of threads 62 num_threads = process.GetNumThreads() 63 64 # Using std::thread may involve extra threads, so we assert that there are 65 # at least 4 rather than exactly 4. 66 self.assertTrue( 67 num_threads >= 13, 68 "Number of expected threads and actual threads do not match.", 69 ) 70 71 @skipIfDarwin # rdar://33462362 72 @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373 73 def test_unique_stacks(self): 74 """Test backtrace unique with multiple threads executing the same stack.""" 75 self.build() 76 exe = self.getBuildArtifact("a.out") 77 self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) 78 79 # Set a break point on the thread3 notify all (should get hit on threads 4-13). 80 lldbutil.run_break_set_by_file_and_line( 81 self, "main.cpp", self.thread3_before_lock_line, num_expected_locations=1 82 ) 83 84 # Run the program. 85 self.runCmd("run", RUN_SUCCEEDED) 86 87 # Stopped once. 88 self.expect( 89 "thread list", 90 STOPPED_DUE_TO_BREAKPOINT, 91 substrs=["stop reason = breakpoint 1."], 92 ) 93 94 process = self.process() 95 96 # Get the number of threads 97 num_threads = process.GetNumThreads() 98 99 # Using std::thread may involve extra threads, so we assert that there are 100 # at least 10 thread3's rather than exactly 10. 101 self.assertTrue( 102 num_threads >= 10, 103 "Number of expected threads and actual threads do not match.", 104 ) 105 106 # Attempt to walk each of the thread's executing the thread3 function to 107 # the same breakpoint. 108 def is_thread3(thread): 109 for frame in thread: 110 if frame.GetFunctionName() is None: 111 continue 112 if "thread3" in frame.GetFunctionName(): 113 return True 114 return False 115 116 expect_threads = "" 117 for i in range(num_threads): 118 thread = process.GetThreadAtIndex(i) 119 self.assertTrue(thread.IsValid()) 120 if not is_thread3(thread): 121 continue 122 123 # If we aren't stopped out the thread breakpoint try to resume. 124 if thread.GetStopReason() != lldb.eStopReasonBreakpoint: 125 self.runCmd("thread continue %d" % (i + 1)) 126 self.assertStopReason(thread.GetStopReason(), lldb.eStopReasonBreakpoint) 127 128 expect_threads += " #%d" % (i + 1) 129 130 # Construct our expected back trace string 131 expect_string = "10 thread(s)%s" % (expect_threads) 132 133 # Now that we are stopped, we should have 10 threads waiting in the 134 # thread3 function. All of these threads should show as one stack. 135 self.expect( 136 "thread backtrace unique", 137 "Backtrace with unique stack shown correctly", 138 substrs=[expect_string, "main.cpp:%d" % self.thread3_before_lock_line], 139 ) 140