diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -267,6 +267,12 @@ if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop()) return true; + if (stop_reason == eStopReasonFork || stop_reason == eStopReasonVFork || + stop_reason == eStopReasonVForkDone) { + LLDB_LOGF(log, "ThreadPlanCallFunction::PlanExplainsStop not done for fork stop reasons."); + return false; + } + // One more quirk here. If this event was from Halt interrupting the target, // then we should not consider ourselves complete. Return true to // acknowledge the stop. @@ -371,7 +377,7 @@ #ifndef SINGLE_STEP_EXPRESSIONS Thread &thread = GetThread(); - m_subplan_sp = std::make_shared(thread, m_start_addr, + m_subplan_sp = std::make_shared(thread, m_start_addr, m_stop_other_threads); thread.QueueThreadPlan(m_subplan_sp, false); diff --git a/lldb/test/API/commands/expression/fork/Makefile b/lldb/test/API/commands/expression/fork/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/fork/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/expression/fork/TestForkExprs.py b/lldb/test/API/commands/expression/fork/TestForkExprs.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/fork/TestForkExprs.py @@ -0,0 +1,41 @@ +""" +Test some more expression commands. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandsForkExpressions(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + @skipUnlessPlatform(["linux"]) + def test_more_expr_commands(self): + """Test some more expression commands.""" + self.build() + + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here to evaluate expressions', + lldb.SBFileSpec("main.cpp")) + + self.assertTrue(bkpt.IsValid()) + bkpt.SetEnabled(False) + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(True) + frame = self.thread.GetFrameAtIndex(0) + + value = frame.EvaluateExpression("do_fork(argv, envp)", options) + self.assertTrue(value.IsValid()) + self.assertSuccess(value.GetError()) + value = frame.EvaluateExpression("do_vfork(argv, envp)", options) + self.assertTrue(value.IsValid()) + self.assertSuccess(value.GetError()) diff --git a/lldb/test/API/commands/expression/fork/main.cpp b/lldb/test/API/commands/expression/fork/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/commands/expression/fork/main.cpp @@ -0,0 +1,29 @@ +#include +#include + +pid_t do_fork(char *const argv[], char *const envp[]) { + pid_t pid = fork(); + if (pid == 0) + execve(argv[0], argv, envp); + return pid; +} + +pid_t do_vfork(char *const argv[], char *const envp[]) { + pid_t pid = vfork(); + if (pid == 0) + execve(argv[0], argv, envp); + return pid; +} + +int main(int argc, char *const argv[], char *const envp[]) { + // Stop here to evaluate expressions + // Optionally call do_fork() when argc is 4 to make sure do_fork() doesn't get + // dead stripped + if (argc == 4) + do_fork(argv, envp); + // Optionally call do_vfork() when argc is 5 to make sure do_fork() doesn't + // get dead stripped + if (argc == 5) + do_vfork(argv, envp); + return 0; +}