diff --git a/lldb/source/Target/ThreadPlan.cpp b/lldb/source/Target/ThreadPlan.cpp --- a/lldb/source/Target/ThreadPlan.cpp +++ b/lldb/source/Target/ThreadPlan.cpp @@ -171,6 +171,9 @@ 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 --- /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 --- /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 --- /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(); +}