"""
Make sure that the concurrent vfork() from multiple threads works correctly.
"""
import lldb
import lldbsuite.test.lldbutil as lldbutil
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
class TestConcurrentVFork(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def build_run_to_breakpoint(self, use_fork, call_exec):
self.build()
args = []
if use_fork:
args.append("--fork")
if call_exec:
args.append("--exec")
launch_info = lldb.SBLaunchInfo(args)
launch_info.SetWorkingDirectory(self.getBuildDir())
return lldbutil.run_to_source_breakpoint(
self, "// break here", lldb.SBFileSpec("main.cpp")
)
def follow_parent_helper(self, use_fork, call_exec):
(target, process, thread, bkpt) = self.build_run_to_breakpoint(
use_fork, call_exec
)
parent_pid = target.FindFirstGlobalVariable("g_pid").GetValueAsUnsigned()
self.runCmd("settings set target.process.follow-fork-mode parent")
self.runCmd("settings set target.process.stop-on-exec False", check=False)
self.expect(
"continue", substrs=[f"Process {parent_pid} exited with status = 0"]
)
def follow_child_helper(self, use_fork, call_exec):
self.build_run_to_breakpoint(use_fork, call_exec)
self.runCmd("settings set target.process.follow-fork-mode child")
self.runCmd("settings set target.process.stop-on-exec False", check=False)
# Child process exits with code "index + 10" since index is [0-4]
# so the exit code should be 1[0-4]
self.expect("continue", patterns=[r"exited with status = 1[0-4]"])
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_parent_vfork_no_exec(self):
"""
Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent.
And follow-parent successfully detach all child processes and exit debugger without calling exec.
"""
self.follow_parent_helper(use_fork=False, call_exec=False)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_parent_fork_no_exec(self):
"""
Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-parent.
And follow-parent successfully detach all child processes and exit debugger without calling exec
"""
self.follow_parent_helper(use_fork=True, call_exec=False)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_parent_vfork_call_exec(self):
"""
Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent.
And follow-parent successfully detach all child processes and exit debugger after calling exec.
"""
self.follow_parent_helper(use_fork=False, call_exec=True)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_parent_fork_call_exec(self):
"""
Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent.
And follow-parent successfully detach all child processes and exit debugger after calling exec.
"""
self.follow_parent_helper(use_fork=True, call_exec=True)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_child_vfork_no_exec(self):
"""
Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child.
And follow-child successfully detach parent process and exit child process with correct exit code without calling exec.
"""
self.follow_child_helper(use_fork=False, call_exec=False)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_child_fork_no_exec(self):
"""
Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child.
And follow-child successfully detach parent process and exit child process with correct exit code without calling exec.
"""
self.follow_child_helper(use_fork=True, call_exec=False)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_child_vfork_call_exec(self):
"""
Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child.
And follow-child successfully detach parent process and exit child process with correct exit code after calling exec.
"""
self.follow_child_helper(use_fork=False, call_exec=True)
@skipUnlessPlatform(["linux"])
# https://github.com/llvm/llvm-project/issues/85084.
@skipIf(oslist=["linux"], archs=["aarch64", "arm"])
def test_follow_child_fork_call_exec(self):
"""
Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child.
And follow-child successfully detach parent process and exit child process with correct exit code after calling exec.
"""
self.follow_child_helper(use_fork=True, call_exec=True)