diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1062,6 +1062,8 @@ if (action == nullptr) { LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(), thread->GetID()); + // Make sure we reset the stop reason for all the threads. + static_cast(*thread).ResetStopReason(); continue; } diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -94,6 +94,8 @@ void SetStopped(); + void ResetStopReason(); + // Member Variables lldb::StateType m_state; ThreadStopInfo m_stop_info; diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp --- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -396,7 +396,10 @@ void NativeThreadLinux::SetStoppedWithNoReason() { SetStopped(); + ResetStopReason(); +} +void NativeThreadLinux::ResetStopReason() { m_stop_info.reason = StopReason::eStopReasonNone; m_stop_info.details.signal.signo = 0; } diff --git a/lldb/test/API/functionalities/thread/break_step_other/Makefile b/lldb/test/API/functionalities/thread/break_step_other/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/thread/break_step_other/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp +ENABLE_THREADS := YES + +include Makefile.rules diff --git a/lldb/test/API/functionalities/thread/break_step_other/TestThreadBreakStepOther.py b/lldb/test/API/functionalities/thread/break_step_other/TestThreadBreakStepOther.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/thread/break_step_other/TestThreadBreakStepOther.py @@ -0,0 +1,62 @@ +""" +Test stop reasons after hitting and deleting a breakpoint and +stepping another thread. Scenario: + - run a thread + - stop the thread at a breakpoint + - delete the breakpoint + - single step on the main thread +The thread stopped at the deleted breakpoint should have stop reason +'none'. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ThreadBreakStepOtherTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test_hit_breakpoint_delete_step_other_thread(self): + main_source_file = lldb.SBFileSpec("main.cpp") + self.build() + (target, process, main_thread, _) = lldbutil.run_to_source_breakpoint( + self, "// main break here", main_source_file, only_one_thread = False) + + # Run until the breakpoint in the thread. + thread_breakpoint = target.BreakpointCreateBySourceRegex( + "// thread break here", main_source_file) + self.assertGreater( + thread_breakpoint.GetNumLocations(), + 0, + "thread breakpoint has no locations associated with it.") + process.Continue() + stopped_threads = lldbutil.get_threads_stopped_at_breakpoint( + process, thread_breakpoint) + self.assertEquals( + 1, + len(stopped_threads), + "only one thread expected stopped at the thread breakpoint") + breakpoint_thread = stopped_threads[0] + + # Delete the breakpint in the thread and do a step in the main thread. + target.BreakpointDelete(thread_breakpoint.GetID()) + main_thread.StepInstruction(False) + + # Check the stop reasons. + reason = main_thread.GetStopReason() + self.assertEqual( + lldb.eStopReasonPlanComplete, + reason, + "Expected thread stop reason 'plancomplete', but got '%s'" % + lldbutil.stop_reason_to_str(reason)) + + reason = breakpoint_thread.GetStopReason() + self.assertEqual( + lldb.eStopReasonNone, + reason, + "Expected thread stop reason 'none', but got '%s'" % + lldbutil.stop_reason_to_str(reason)) diff --git a/lldb/test/API/functionalities/thread/break_step_other/main.cpp b/lldb/test/API/functionalities/thread/break_step_other/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/functionalities/thread/break_step_other/main.cpp @@ -0,0 +1,27 @@ +#include +#include "pseudo_barrier.h" + +// Barrier for starting the thread and reaching the loop in main. +pseudo_barrier_t g_barrier; +volatile int g_foo = 0; + +void thread_func() { + // Wait until all the threads are running + pseudo_barrier_wait(g_barrier); + g_foo = 0; // thread break here +} + +int main() { + g_foo = 0; // main break here + + pseudo_barrier_init(g_barrier, 2); + std::thread t(thread_func); + pseudo_barrier_wait(g_barrier); + + // A dummy loop to have something to step through. + unsigned int i = 0; + while (true) { + g_foo = ++i; + } + return 0; +}