[Lldb-commits] [lldb] af9e1fa - [lldb] Detach the child process when stepping over a fork

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Wed Apr 5 04:25:58 PDT 2023


Author: Pavel Labath
Date: 2023-04-05T13:25:43+02:00
New Revision: af9e1fa178433653eb3d36c42cad016449873cfc

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

LOG: [lldb] Detach the child process when stepping over a fork

Step over thread plans were claiming to explain the fork stop reasons,
which prevented the default fork logic (detaching from the child
process) from kicking in. This patch changes that.

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

Added: 
    lldb/test/API/functionalities/fork/resumes-child/Makefile
    lldb/test/API/functionalities/fork/resumes-child/TestForkResumesChild.py
    lldb/test/API/functionalities/fork/resumes-child/main.cpp

Modified: 
    lldb/source/Target/ThreadPlan.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp
index 9913ecb591fa7..7927fc3140145 100644
--- a/lldb/source/Target/ThreadPlan.cpp
+++ b/lldb/source/Target/ThreadPlan.cpp
@@ -171,6 +171,9 @@ bool ThreadPlan::IsUsuallyUnexplainedStopReason(lldb::StopReason reason) {
   case eStopReasonExec:
   case eStopReasonThreadExiting:
   case eStopReasonInstrumentation:
+  case eStopReasonFork:
+  case eStopReasonVFork:
+  case eStopReasonVForkDone:
     return true;
   default:
     return false;

diff  --git a/lldb/test/API/functionalities/fork/resumes-child/Makefile b/lldb/test/API/functionalities/fork/resumes-child/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/functionalities/fork/resumes-child/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules

diff  --git a/lldb/test/API/functionalities/fork/resumes-child/TestForkResumesChild.py b/lldb/test/API/functionalities/fork/resumes-child/TestForkResumesChild.py
new file mode 100644
index 0000000000000..70df4f1c51a7c
--- /dev/null
+++ b/lldb/test/API/functionalities/fork/resumes-child/TestForkResumesChild.py
@@ -0,0 +1,22 @@
+"""
+Make sure that the fork child keeps running.
+"""
+
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+
+class TestForkResumesChild(TestBase):
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    @skipIfWindows
+    def test_step_over_fork(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(self, "// break here", lldb.SBFileSpec("main.cpp"))
+        self.runCmd("next")
+        self.expect("continue", substrs = ["exited with status = 0"])

diff  --git a/lldb/test/API/functionalities/fork/resumes-child/main.cpp b/lldb/test/API/functionalities/fork/resumes-child/main.cpp
new file mode 100644
index 0000000000000..2d37f323bdf6a
--- /dev/null
+++ b/lldb/test/API/functionalities/fork/resumes-child/main.cpp
@@ -0,0 +1,29 @@
+#include <cassert>
+#include <chrono>
+#include <cstdlib>
+#include <sys/wait.h>
+#include <thread>
+#include <unistd.h>
+
+int main() {
+  pid_t fork_result = fork(); // break here
+  assert(fork_result >= 0);
+  if (fork_result == 0) {
+    // child
+    _exit(47);
+  }
+  // parent
+  // Use polling to avoid blocking if the child is not actually resumed.
+  auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(10);
+  std::chrono::milliseconds poll_interval{10};
+  while (std::chrono::steady_clock::now() < deadline) {
+    int status;
+    pid_t waitpid_result = waitpid(fork_result, &status, WNOHANG);
+    if (waitpid_result == fork_result)
+      return 0;
+    assert(waitpid_result == 0);
+    std::this_thread::sleep_for(poll_interval);
+    poll_interval *= 2;
+  }
+  abort();
+}


        


More information about the lldb-commits mailing list