2 * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/types.h>
31 #include <sys/ptrace.h>
40 * Verify that a parent debugger process "sees" the exit of a debugged
41 * process exactly once when attached via PT_TRACE_ME.
43 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me);
44 ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
49 ATF_REQUIRE((child = fork()) != -1);
52 ATF_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
62 /* The first wait() should report the stop from SIGSTOP. */
63 wpid = waitpid(child, &status, 0);
64 ATF_REQUIRE(wpid == child);
65 ATF_REQUIRE(WIFSTOPPED(status));
66 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
68 /* Continue the child ignoring the SIGSTOP. */
69 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
71 /* The second wait() should report the exit status. */
72 wpid = waitpid(child, &status, 0);
73 ATF_REQUIRE(wpid == child);
74 ATF_REQUIRE(WIFEXITED(status));
75 ATF_REQUIRE(WEXITSTATUS(status) == 1);
77 /* The child should no longer exist. */
78 wpid = waitpid(child, &status, 0);
79 ATF_REQUIRE(wpid == -1);
80 ATF_REQUIRE(errno == ECHILD);
84 * Verify that a parent debugger process "sees" the exit of a debugged
85 * process exactly once when attached via PT_ATTACH.
87 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach);
88 ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
94 ATF_REQUIRE(pipe(cpipe) == 0);
95 ATF_REQUIRE((child = fork()) != -1);
100 /* Wait for the parent to attach. */
101 ATF_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0);
107 /* Parent process. */
109 /* Attach to the child process. */
110 ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
112 /* The first wait() should report the SIGSTOP from PT_ATTACH. */
113 wpid = waitpid(child, &status, 0);
114 ATF_REQUIRE(wpid == child);
115 ATF_REQUIRE(WIFSTOPPED(status));
116 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
118 /* Continue the child ignoring the SIGSTOP. */
119 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
121 /* Signal the child to exit. */
124 /* The second wait() should report the exit status. */
125 wpid = waitpid(child, &status, 0);
126 ATF_REQUIRE(wpid == child);
127 ATF_REQUIRE(WIFEXITED(status));
128 ATF_REQUIRE(WEXITSTATUS(status) == 1);
130 /* The child should no longer exist. */
131 wpid = waitpid(child, &status, 0);
132 ATF_REQUIRE(wpid == -1);
133 ATF_REQUIRE(errno == ECHILD);
139 ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me);
140 ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
142 return (atf_no_error());