255 lines · python
1"""2Test that single thread step over deadlock issue can be resolved 3after timeout.4"""5 6import lldb7from lldbsuite.test.decorators import *8from lldbsuite.test.lldbtest import *9from lldbsuite.test import lldbutil10 11 12class SingleThreadStepTimeoutTestCase(TestBase):13 NO_DEBUG_INFO_TESTCASE = True14 15 def setUp(self):16 TestBase.setUp(self)17 self.main_source = "main.cpp"18 self.build()19 20 def verify_hit_correct_line(self, pattern):21 target_line = line_number(self.main_source, pattern)22 self.assertNotEqual(target_line, 0, "Could not find source pattern " + pattern)23 cur_line = self.thread.frames[0].GetLineEntry().GetLine()24 self.assertEqual(25 cur_line,26 target_line,27 "Stepped to line %d instead of expected %d with pattern '%s'."28 % (cur_line, target_line, pattern),29 )30 31 def step_over_deadlock_helper(self):32 (target, _, self.thread, _) = lldbutil.run_to_source_breakpoint(33 self, "// Set breakpoint1 here", lldb.SBFileSpec(self.main_source)34 )35 36 signal_main_thread_value = target.FindFirstGlobalVariable("signal_main_thread")37 self.assertTrue(signal_main_thread_value.IsValid())38 39 # Change signal_main_thread global variable to 1 so that worker thread loop can40 # terminate and move forward to signal main thread41 signal_main_thread_value.SetValueFromCString("1")42 43 self.thread.StepOver(lldb.eOnlyThisThread)44 self.verify_hit_correct_line("// Finish step-over from breakpoint1")45 46 @skipIfWindows47 def test_step_over_deadlock_small_timeout_fast_stepping(self):48 """Test single thread step over deadlock on other threads can be resolved after timeout with small timeout and fast stepping."""49 self.dbg.HandleCommand(50 "settings set target.process.thread.single-thread-plan-timeout 10"51 )52 self.dbg.HandleCommand("settings set target.use-fast-stepping true")53 self.step_over_deadlock_helper()54 55 @skipIfWindows56 def test_step_over_deadlock_small_timeout_slow_stepping(self):57 """Test single thread step over deadlock on other threads can be resolved after timeout with small timeout and slow stepping."""58 self.dbg.HandleCommand(59 "settings set target.process.thread.single-thread-plan-timeout 10"60 )61 self.dbg.HandleCommand("settings set target.use-fast-stepping false")62 self.step_over_deadlock_helper()63 64 @skipIfWindows65 def test_step_over_deadlock_large_timeout_fast_stepping(self):66 """Test single thread step over deadlock on other threads can be resolved after timeout with large timeout and fast stepping."""67 self.dbg.HandleCommand(68 "settings set target.process.thread.single-thread-plan-timeout 2000"69 )70 self.dbg.HandleCommand("settings set target.use-fast-stepping true")71 self.step_over_deadlock_helper()72 73 @skipIfWindows74 def test_step_over_deadlock_large_timeout_slow_stepping(self):75 """Test single thread step over deadlock on other threads can be resolved after timeout with large timeout and slow stepping."""76 self.dbg.HandleCommand(77 "settings set target.process.thread.single-thread-plan-timeout 2000"78 )79 self.dbg.HandleCommand("settings set target.use-fast-stepping false")80 self.step_over_deadlock_helper()81 82 def step_over_multi_calls_helper(self):83 (target, _, self.thread, _) = lldbutil.run_to_source_breakpoint(84 self, "// Set breakpoint2 here", lldb.SBFileSpec(self.main_source)85 )86 self.thread.StepOver(lldb.eOnlyThisThread)87 self.verify_hit_correct_line("// Finish step-over from breakpoint2")88 89 @skipIfWindows90 def test_step_over_multi_calls_small_timeout_fast_stepping(self):91 """Test step over source line with multiple call instructions works fine with small timeout and fast stepping."""92 self.dbg.HandleCommand(93 "settings set target.process.thread.single-thread-plan-timeout 10"94 )95 self.dbg.HandleCommand("settings set target.use-fast-stepping true")96 self.step_over_multi_calls_helper()97 98 @skipIfWindows99 def test_step_over_multi_calls_small_timeout_slow_stepping(self):100 """Test step over source line with multiple call instructions works fine with small timeout and slow stepping."""101 self.dbg.HandleCommand(102 "settings set target.process.thread.single-thread-plan-timeout 10"103 )104 self.dbg.HandleCommand("settings set target.use-fast-stepping false")105 self.step_over_multi_calls_helper()106 107 @skipIfWindows108 def test_step_over_multi_calls_large_timeout_fast_stepping(self):109 """Test step over source line with multiple call instructions works fine with large timeout and fast stepping."""110 self.dbg.HandleCommand(111 "settings set target.process.thread.single-thread-plan-timeout 2000"112 )113 self.dbg.HandleCommand("settings set target.use-fast-stepping true")114 self.step_over_multi_calls_helper()115 116 @skipIfWindows117 def test_step_over_multi_calls_large_timeout_slow_stepping(self):118 """Test step over source line with multiple call instructions works fine with large timeout and slow stepping."""119 self.dbg.HandleCommand(120 "settings set target.process.thread.single-thread-plan-timeout 2000"121 )122 self.dbg.HandleCommand("settings set target.use-fast-stepping false")123 self.step_over_multi_calls_helper()124 125 @skipIfWindows126 def test_step_over_deadlock_with_inner_breakpoint_continue(self):127 """Test step over deadlock function with inner breakpoint will trigger the breakpoint128 and later continue will finish the stepping.129 """130 self.dbg.HandleCommand(131 "settings set target.process.thread.single-thread-plan-timeout 2000"132 )133 (target, process, self.thread, _) = lldbutil.run_to_source_breakpoint(134 self, "// Set breakpoint1 here", lldb.SBFileSpec(self.main_source)135 )136 137 signal_main_thread_value = target.FindFirstGlobalVariable("signal_main_thread")138 self.assertTrue(signal_main_thread_value.IsValid())139 140 # Change signal_main_thread global variable to 1 so that worker thread loop can141 # terminate and move forward to signal main thread142 signal_main_thread_value.SetValueFromCString("1")143 144 # Set breakpoint on inner function call145 inner_breakpoint = target.BreakpointCreateByLocation(146 lldb.SBFileSpec(self.main_source),147 line_number("main.cpp", "// Set interrupt breakpoint here"),148 0,149 0,150 lldb.SBFileSpecList(),151 False,152 )153 154 # Step over will hit the inner breakpoint and stop155 self.thread.StepOver(lldb.eOnlyThisThread)156 self.assertStopReason(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint)157 thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(158 process, inner_breakpoint159 )160 self.assertTrue(161 thread1.IsValid(),162 "We are indeed stopped at inner breakpoint inside deadlock_func",163 )164 165 # Continue the process should complete the step-over166 process.Continue()167 self.assertState(process.GetState(), lldb.eStateStopped)168 self.assertStopReason(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)169 170 self.verify_hit_correct_line("// Finish step-over from breakpoint1")171 172 @skipIfWindows173 def test_step_over_deadlock_with_inner_breakpoint_step(self):174 """Test step over deadlock function with inner breakpoint will trigger the breakpoint175 and later step still works176 """177 self.dbg.HandleCommand(178 "settings set target.process.thread.single-thread-plan-timeout 2000"179 )180 (target, process, self.thread, _) = lldbutil.run_to_source_breakpoint(181 self, "// Set breakpoint1 here", lldb.SBFileSpec(self.main_source)182 )183 184 signal_main_thread_value = target.FindFirstGlobalVariable("signal_main_thread")185 self.assertTrue(signal_main_thread_value.IsValid())186 187 # Change signal_main_thread global variable to 1 so that worker thread loop can188 # terminate and move forward to signal main thread189 signal_main_thread_value.SetValueFromCString("1")190 191 # Set breakpoint on inner function call192 inner_breakpoint = target.BreakpointCreateByLocation(193 lldb.SBFileSpec(self.main_source),194 line_number("main.cpp", "// Set interrupt breakpoint here"),195 0,196 0,197 lldb.SBFileSpecList(),198 False,199 )200 201 # Step over will hit the inner breakpoint and stop202 self.thread.StepOver(lldb.eOnlyThisThread)203 self.assertStopReason(self.thread.GetStopReason(), lldb.eStopReasonBreakpoint)204 thread1 = lldbutil.get_one_thread_stopped_at_breakpoint(205 process, inner_breakpoint206 )207 self.assertTrue(208 thread1.IsValid(),209 "We are indeed stopped at inner breakpoint inside deadlock_func",210 )211 212 # Step still works213 self.thread.StepOver(lldb.eOnlyThisThread)214 self.assertState(process.GetState(), lldb.eStateStopped)215 self.assertStopReason(self.thread.GetStopReason(), lldb.eStopReasonPlanComplete)216 217 self.verify_hit_correct_line("// Finish step-over from inner breakpoint")218 219 @skipIfWindows220 def test_step_over_deadlock_with_user_async_interrupt(self):221 """Test step over deadlock function with large timeout then send async interrupt222 should report correct stop reason223 """224 225 self.dbg.HandleCommand(226 "settings set target.process.thread.single-thread-plan-timeout 2000000"227 )228 229 (target, process, self.thread, _) = lldbutil.run_to_source_breakpoint(230 self, "// Set breakpoint1 here", lldb.SBFileSpec(self.main_source)231 )232 233 signal_main_thread_value = target.FindFirstGlobalVariable("signal_main_thread")234 self.assertTrue(signal_main_thread_value.IsValid())235 236 # Change signal_main_thread global variable to 1 so that worker thread loop can237 # terminate and move forward to signal main thread238 signal_main_thread_value.SetValueFromCString("1")239 240 self.dbg.SetAsync(True)241 242 # This stepping should block due to large timeout and should be interrupted by the243 # async interrupt from the worker thread244 self.thread.StepOver(lldb.eOnlyThisThread)245 time.sleep(1)246 247 listener = self.dbg.GetListener()248 lldbutil.expect_state_changes(self, listener, process, [lldb.eStateRunning])249 self.dbg.SetAsync(False)250 251 process.SendAsyncInterrupt()252 253 lldbutil.expect_state_changes(self, listener, process, [lldb.eStateStopped])254 self.assertStopReason(self.thread.GetStopReason(), lldb.eStopReasonSignal)255