Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F169765298
D2809.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D2809.diff
View Options
Index: head/sys/kern/sys_process.c
===================================================================
--- head/sys/kern/sys_process.c
+++ head/sys/kern/sys_process.c
@@ -947,7 +947,15 @@
}
break;
case PT_DETACH:
- /* reset process parent */
+ /*
+ * Reset the process parent.
+ *
+ * NB: This clears P_TRACED before reparenting
+ * a detached process back to its original
+ * parent. Otherwise the debugee will be set
+ * as an orphan of the debugger.
+ */
+ p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
@@ -963,7 +971,6 @@
} else
CTR1(KTR_PTRACE, "PT_DETACH: pid %d", p->p_pid);
p->p_oppid = 0;
- p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
p->p_stops = 0;
/* should we send SIGCHLD? */
Index: head/tests/sys/kern/ptrace_test.c
===================================================================
--- head/tests/sys/kern/ptrace_test.c
+++ head/tests/sys/kern/ptrace_test.c
@@ -50,7 +50,7 @@
#exp " not met"); \
} while (0)
-static void __dead2
+static __dead2 void
child_fail_require(const char *file, int line, const char *str)
{
char buf[128];
@@ -60,6 +60,58 @@
_exit(32);
}
+static void
+trace_me(void)
+{
+
+ /* Attach the parent process as a tracer of this process. */
+ CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+ /* Trigger a stop. */
+ raise(SIGSTOP);
+}
+
+static void
+attach_child(pid_t pid)
+{
+ pid_t wpid;
+ int status;
+
+ ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
+
+ wpid = waitpid(pid, &status, 0);
+ ATF_REQUIRE(wpid == pid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+}
+
+static void
+wait_for_zombie(pid_t pid)
+{
+
+ /*
+ * Wait for a process to exit. This is kind of gross, but
+ * there is not a better way.
+ */
+ for (;;) {
+ struct kinfo_proc kp;
+ size_t len;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ len = sizeof(kp);
+ if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
+ /* The KERN_PROC_PID sysctl fails for zombies. */
+ ATF_REQUIRE(errno == ESRCH);
+ break;
+ }
+ usleep(5000);
+ }
+}
+
/*
* Verify that a parent debugger process "sees" the exit of a debugged
* process exactly once when attached via PT_TRACE_ME.
@@ -73,10 +125,7 @@
ATF_REQUIRE((child = fork()) != -1);
if (child == 0) {
/* Child process. */
- CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- /* Trigger a stop. */
- raise(SIGSTOP);
+ trace_me();
exit(1);
}
@@ -131,13 +180,7 @@
/* Parent process. */
/* Attach to the child process. */
- ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
-
- /* The first wait() should report the SIGSTOP from PT_ATTACH. */
- wpid = waitpid(child, &status, 0);
- ATF_REQUIRE(wpid == child);
- ATF_REQUIRE(WIFSTOPPED(status));
- ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+ attach_child(child);
/* Continue the child ignoring the SIGSTOP. */
ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
@@ -223,27 +266,7 @@
ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
close(cpipe[0]);
- /*
- * Wait for the child to exit. This is kind of gross, but
- * there is not a better way.
- */
- for (;;) {
- struct kinfo_proc kp;
- size_t len;
- int mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = child;
- len = sizeof(kp);
- if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
- /* The KERN_PROC_PID sysctl fails for zombies. */
- ATF_REQUIRE(errno == ESRCH);
- break;
- }
- usleep(5000);
- }
+ wait_for_zombie(child);
/*
* This wait should return a pid of 0 to indicate no status to
@@ -357,27 +380,7 @@
ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
close(cpipe[0]);
- /*
- * Wait for the child to exit. This is kind of gross, but
- * there is not a better way.
- */
- for (;;) {
- struct kinfo_proc kp;
- size_t len;
- int mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = child;
- len = sizeof(kp);
- if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
- /* The KERN_PROC_PID sysctl fails for zombies. */
- ATF_REQUIRE(errno == ESRCH);
- break;
- }
- usleep(5000);
- }
+ wait_for_zombie(child);
/*
* This wait should return a pid of 0 to indicate no status to
@@ -401,6 +404,468 @@
ATF_REQUIRE(WEXITSTATUS(status) == 1);
}
+/*
+ * The parent process should always act the same regardless of how the
+ * debugger is attached to it.
+ */
+static __dead2 void
+follow_fork_parent(void)
+{
+ pid_t fpid, wpid;
+ int status;
+
+ CHILD_REQUIRE((fpid = fork()) != -1);
+
+ if (fpid == 0)
+ /* Child */
+ exit(2);
+
+ wpid = waitpid(fpid, &status, 0);
+ CHILD_REQUIRE(wpid == fpid);
+ CHILD_REQUIRE(WIFEXITED(status));
+ CHILD_REQUIRE(WEXITSTATUS(status) == 2);
+
+ exit(1);
+}
+
+/*
+ * Helper routine for follow fork tests. This waits for two stops
+ * that report both "sides" of a fork. It returns the pid of the new
+ * child process.
+ */
+static pid_t
+handle_fork_events(pid_t parent)
+{
+ struct ptrace_lwpinfo pl;
+ bool fork_reported[2];
+ pid_t child, wpid;
+ int i, status;
+
+ fork_reported[0] = false;
+ fork_reported[1] = false;
+ child = -1;
+
+ /*
+ * Each process should report a fork event. The parent should
+ * report a PL_FLAG_FORKED event, and the child should report
+ * a PL_FLAG_CHILD event.
+ */
+ for (i = 0; i < 2; i++) {
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid > 0);
+ ATF_REQUIRE(WIFSTOPPED(status));
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
+ sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
+ 0);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
+ (PL_FLAG_FORKED | PL_FLAG_CHILD));
+ if (pl.pl_flags & PL_FLAG_CHILD) {
+ ATF_REQUIRE(wpid != parent);
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+ ATF_REQUIRE(!fork_reported[1]);
+ if (child == -1)
+ child = wpid;
+ else
+ ATF_REQUIRE(child == wpid);
+ fork_reported[1] = true;
+ } else {
+ ATF_REQUIRE(wpid == parent);
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+ ATF_REQUIRE(!fork_reported[0]);
+ if (child == -1)
+ child = pl.pl_child_pid;
+ else
+ ATF_REQUIRE(child == pl.pl_child_pid);
+ fork_reported[0] = true;
+ }
+ }
+
+ return (child);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork and
+ * that the traced parent sees the exit of the child after the debugger
+ * when both processes remain attached to the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
+ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The child can't exit until the grandchild reports status, so the
+ * grandchild should report its exit first to the debugger.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the new
+ * child process is detached after it reports its fork.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
+ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the grandchild now, only the
+ * child.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the
+ * traced parent is detached after the fork.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
+ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The child can't exit until the grandchild reports status, so the
+ * grandchild should report its exit first to the debugger.
+ *
+ * Even though the child process is detached, it is still a
+ * child of the debugger, so it will still report it's exit
+ * after the grandchild.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+static void
+attach_fork_parent(int cpipe[2])
+{
+ pid_t fpid;
+
+ close(cpipe[0]);
+
+ /* Double-fork to disassociate from the debugger. */
+ CHILD_REQUIRE((fpid = fork()) != -1);
+ if (fpid != 0)
+ exit(3);
+
+ /* Send the pid of the disassociated child to the debugger. */
+ fpid = getpid();
+ CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
+
+ /* Wait for the debugger to attach. */
+ CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork and
+ * that the traced parent sees the exit of the child after the debugger
+ * when both processes remain attached to the debugger. In this test
+ * the parent that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The fork parent can't exit until the child reports status,
+ * so the child should report its exit first to the debugger.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the new
+ * child process is detached after it reports its fork. In this test
+ * the parent that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the child now, only the fork
+ * parent.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the
+ * traced parent is detached after the fork. In this test the parent
+ * that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the fork parent now, only
+ * the child.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -408,6 +873,14 @@
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
+ ATF_TP_ADD_TC(tp,
+ ptrace__follow_fork_child_detached_unrelated_debugger);
+ ATF_TP_ADD_TC(tp,
+ ptrace__follow_fork_parent_detached_unrelated_debugger);
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Sep 3, 12:14 PM (22 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37967323
Default Alt Text
D2809.diff (17 KB)
Attached To
Mode
D2809: Fix an orphan bug and add tests for fork following.
Attached
Detach File
Event Timeline
Log In to Comment