[Lldb-commits] [lldb] 56de738 - [lldb-server] Reset stop reason of all threads when resuming

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed May 20 02:08:53 PDT 2020


Author: Jaroslav Sevcik
Date: 2020-05-20T11:08:34+02:00
New Revision: 56de738d18e11c86169f0248b97b2854c37e35ce

URL: https://github.com/llvm/llvm-project/commit/56de738d18e11c86169f0248b97b2854c37e35ce
DIFF: https://github.com/llvm/llvm-project/commit/56de738d18e11c86169f0248b97b2854c37e35ce.diff

LOG: [lldb-server] Reset stop reason of all threads when resuming

Summary:
This patch makes the stop reason reset logic similar to MacOS' debugserver, where exceptions are reset for all threads when resuming process for stepping or continuing (see [[ https://github.com/llvm/llvm-project/blob/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp#L433 | MachThreadList::ProcessWillResume ]] and [[ https://github.com/llvm/llvm-project/blob/96f3ea0d21b48ca088355db10d4d1a2e9bc9f884/lldb/tools/debugserver/source/MacOSX/MachThread.cpp#L363 | MachThread::ThreadWillResume ]]).

Resetting stop reasons on resume fixes problems where LLDB spuriously reports SIGTRAP signal stop reason for deleted breakpoints (both internal and public) and where  LLDB stops on an internal breakpoint while stepping over while a breakpoint is hit in another thread. See [[ https://bugs.llvm.org/show_bug.cgi?id=45642 | PR45642 ]] for details.

Reviewed By: jingham, labath

Differential Revision: https://reviews.llvm.org/D79308

Added: 
    lldb/test/API/functionalities/thread/break_step_other/Makefile
    lldb/test/API/functionalities/thread/break_step_other/TestThreadBreakStepOther.py
    lldb/test/API/functionalities/thread/break_step_other/main.cpp

Modified: 
    lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
    lldb/source/Plugins/Process/Linux/NativeThreadLinux.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 950cda5c7005..1275e8ac9ce3 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1062,6 +1062,8 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
     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<NativeThreadLinux &>(*thread).ResetStopReason();
       continue;
     }
 

diff  --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index 14eea2df3810..08992f9ebb2a 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -396,7 +396,10 @@ void NativeThreadLinux::SetStoppedByTrace() {
 
 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/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
index fd43c89489f7..af9783b4dbfb 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -94,6 +94,8 @@ class NativeThreadLinux : public NativeThreadProtocol {
 
   void SetStopped();
 
+  void ResetStopReason();
+
   // Member Variables
   lldb::StateType m_state;
   ThreadStopInfo m_stop_info;

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
index 000000000000..c46619c66234
--- /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
index 000000000000..656f269ef1f8
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/break_step_other/TestThreadBreakStepOther.py
@@ -0,0 +1,63 @@
+"""
+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__)
+    NO_DEBUG_INFO_TESTCASE = True
+
+    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
index 000000000000..ce471555d9bd
--- /dev/null
+++ b/lldb/test/API/functionalities/thread/break_step_other/main.cpp
@@ -0,0 +1,27 @@
+#include <thread>
+#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 = 1; // 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.
+  volatile int i = 0;
+  while (g_foo == 0)
+    ++i;
+  t.join();
+  return 0;
+}


        


More information about the lldb-commits mailing list