From f1bf3a3fc11f4d4bcbc4036b23c4fd9dec33c3be Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 12 Jan 2023 14:04:57 +0100 Subject: [PATCH] [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 Signed-off-by: liyiming13 --- lldb/source/Target/ThreadPlan.cpp | 3 ++ .../fork/resumes-child/Makefile | 3 ++ .../resumes-child/TestForkResumesChild.py | 22 ++++++++++++++ .../fork/resumes-child/main.cpp | 29 +++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 lldb/test/API/functionalities/fork/resumes-child/Makefile create mode 100644 lldb/test/API/functionalities/fork/resumes-child/TestForkResumesChild.py create mode 100644 lldb/test/API/functionalities/fork/resumes-child/main.cpp diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp index 9913ecb591fa..7927fc314014 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 000000000000..99998b20bcb0 --- /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 000000000000..70df4f1c51a7 --- /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 000000000000..2d37f323bdf6 --- /dev/null +++ b/lldb/test/API/functionalities/fork/resumes-child/main.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include + +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(); +} -- Gitee