1""" 2Make sure that the concurrent vfork() from multiple threads works correctly. 3""" 4 5import lldb 6import lldbsuite.test.lldbutil as lldbutil 7from lldbsuite.test.lldbtest import * 8from lldbsuite.test.decorators import * 9 10 11class TestConcurrentVFork(TestBase): 12 NO_DEBUG_INFO_TESTCASE = True 13 14 def build_run_to_breakpoint(self, use_fork, call_exec): 15 self.build() 16 17 args = [] 18 if use_fork: 19 args.append("--fork") 20 if call_exec: 21 args.append("--exec") 22 launch_info = lldb.SBLaunchInfo(args) 23 launch_info.SetWorkingDirectory(self.getBuildDir()) 24 25 return lldbutil.run_to_source_breakpoint( 26 self, "// break here", lldb.SBFileSpec("main.cpp") 27 ) 28 29 def follow_parent_helper(self, use_fork, call_exec): 30 (target, process, thread, bkpt) = self.build_run_to_breakpoint( 31 use_fork, call_exec 32 ) 33 34 parent_pid = target.FindFirstGlobalVariable("g_pid").GetValueAsUnsigned() 35 self.runCmd("settings set target.process.follow-fork-mode parent") 36 self.runCmd("settings set target.process.stop-on-exec False", check=False) 37 self.expect( 38 "continue", substrs=[f"Process {parent_pid} exited with status = 0"] 39 ) 40 41 def follow_child_helper(self, use_fork, call_exec): 42 self.build_run_to_breakpoint(use_fork, call_exec) 43 44 self.runCmd("settings set target.process.follow-fork-mode child") 45 self.runCmd("settings set target.process.stop-on-exec False", check=False) 46 # Child process exits with code "index + 10" since index is [0-4] 47 # so the exit code should be 1[0-4] 48 self.expect("continue", patterns=[r"exited with status = 1[0-4]"]) 49 50 @skipUnlessPlatform(["linux"]) 51 # https://github.com/llvm/llvm-project/issues/85084. 52 @skipIf(oslist=["linux"]) 53 def test_follow_parent_vfork_no_exec(self): 54 """ 55 Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. 56 And follow-parent successfully detach all child processes and exit debugger without calling exec. 57 """ 58 self.follow_parent_helper(use_fork=False, call_exec=False) 59 60 @skipUnlessPlatform(["linux"]) 61 # https://github.com/llvm/llvm-project/issues/85084. 62 @skipIf(oslist=["linux"]) 63 def test_follow_parent_fork_no_exec(self): 64 """ 65 Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-parent. 66 And follow-parent successfully detach all child processes and exit debugger without calling exec 67 """ 68 self.follow_parent_helper(use_fork=True, call_exec=False) 69 70 @skipUnlessPlatform(["linux"]) 71 # https://github.com/llvm/llvm-project/issues/85084. 72 @skipIf(oslist=["linux"]) 73 def test_follow_parent_vfork_call_exec(self): 74 """ 75 Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. 76 And follow-parent successfully detach all child processes and exit debugger after calling exec. 77 """ 78 self.follow_parent_helper(use_fork=False, call_exec=True) 79 80 @skipUnlessPlatform(["linux"]) 81 # https://github.com/llvm/llvm-project/issues/85084. 82 @skipIf(oslist=["linux"]) 83 def test_follow_parent_fork_call_exec(self): 84 """ 85 Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-parent. 86 And follow-parent successfully detach all child processes and exit debugger after calling exec. 87 """ 88 self.follow_parent_helper(use_fork=True, call_exec=True) 89 90 @skipUnlessPlatform(["linux"]) 91 # https://github.com/llvm/llvm-project/issues/85084. 92 @skipIf(oslist=["linux"]) 93 def test_follow_child_vfork_no_exec(self): 94 """ 95 Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. 96 And follow-child successfully detach parent process and exit child process with correct exit code without calling exec. 97 """ 98 self.follow_child_helper(use_fork=False, call_exec=False) 99 100 @skipUnlessPlatform(["linux"]) 101 # https://github.com/llvm/llvm-project/issues/85084. 102 @skipIf(oslist=["linux"]) 103 def test_follow_child_fork_no_exec(self): 104 """ 105 Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. 106 And follow-child successfully detach parent process and exit child process with correct exit code without calling exec. 107 """ 108 self.follow_child_helper(use_fork=True, call_exec=False) 109 110 @skipUnlessPlatform(["linux"]) 111 # https://github.com/llvm/llvm-project/issues/85084. 112 @skipIf(oslist=["linux"]) 113 def test_follow_child_vfork_call_exec(self): 114 """ 115 Make sure that debugging concurrent vfork() from multiple threads won't crash lldb during follow-child. 116 And follow-child successfully detach parent process and exit child process with correct exit code after calling exec. 117 """ 118 self.follow_child_helper(use_fork=False, call_exec=True) 119 120 @skipUnlessPlatform(["linux"]) 121 # https://github.com/llvm/llvm-project/issues/85084. 122 @skipIf(oslist=["linux"]) 123 def test_follow_child_fork_call_exec(self): 124 """ 125 Make sure that debugging concurrent fork() from multiple threads won't crash lldb during follow-child. 126 And follow-child successfully detach parent process and exit child process with correct exit code after calling exec. 127 """ 128 self.follow_child_helper(use_fork=True, call_exec=True) 129