[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
This commit is contained in:
Pavel Labath
2023-01-12 14:04:57 +01:00
parent 933d3ee600
commit af9e1fa178
4 changed files with 57 additions and 0 deletions

View File

@@ -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;

View File

@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp
include Makefile.rules

View File

@@ -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"])

View File

@@ -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();
}