1b1dd83d1SJilles Tjoelker /*-
2b1dd83d1SJilles Tjoelker * Copyright (c) 2016 Jilles Tjoelker
3b1dd83d1SJilles Tjoelker * All rights reserved.
4b1dd83d1SJilles Tjoelker *
5b1dd83d1SJilles Tjoelker * Redistribution and use in source and binary forms, with or without
6b1dd83d1SJilles Tjoelker * modification, are permitted provided that the following conditions
7b1dd83d1SJilles Tjoelker * are met:
8b1dd83d1SJilles Tjoelker * 1. Redistributions of source code must retain the above copyright
9b1dd83d1SJilles Tjoelker * notice, this list of conditions and the following disclaimer.
10b1dd83d1SJilles Tjoelker * 2. Redistributions in binary form must reproduce the above copyright
11b1dd83d1SJilles Tjoelker * notice, this list of conditions and the following disclaimer in the
12b1dd83d1SJilles Tjoelker * documentation and/or other materials provided with the distribution.
13b1dd83d1SJilles Tjoelker *
14b1dd83d1SJilles Tjoelker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15b1dd83d1SJilles Tjoelker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16b1dd83d1SJilles Tjoelker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17b1dd83d1SJilles Tjoelker * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18b1dd83d1SJilles Tjoelker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19b1dd83d1SJilles Tjoelker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20b1dd83d1SJilles Tjoelker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21b1dd83d1SJilles Tjoelker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22b1dd83d1SJilles Tjoelker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23b1dd83d1SJilles Tjoelker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24b1dd83d1SJilles Tjoelker * SUCH DAMAGE.
25b1dd83d1SJilles Tjoelker */
26b1dd83d1SJilles Tjoelker
27b1dd83d1SJilles Tjoelker #include <sys/cdefs.h>
28b1dd83d1SJilles Tjoelker #include <sys/procctl.h>
29*ddab8c35SMark Johnston #include <sys/procdesc.h>
30b1dd83d1SJilles Tjoelker #include <sys/wait.h>
31b1dd83d1SJilles Tjoelker
32b1dd83d1SJilles Tjoelker #include <atf-c.h>
33b1dd83d1SJilles Tjoelker #include <errno.h>
34b1dd83d1SJilles Tjoelker #include <signal.h>
35b1dd83d1SJilles Tjoelker #include <unistd.h>
36b1dd83d1SJilles Tjoelker
37fe56b177SJilles Tjoelker static void
dummy_sighandler(int sig __unused,siginfo_t * info __unused,void * ctx __unused)38fe56b177SJilles Tjoelker dummy_sighandler(int sig __unused, siginfo_t *info __unused, void *ctx __unused)
39fe56b177SJilles Tjoelker {
40fe56b177SJilles Tjoelker }
41fe56b177SJilles Tjoelker
42b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_wait_child_first);
ATF_TC_BODY(reaper_wait_child_first,tc)43b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_wait_child_first, tc)
44b1dd83d1SJilles Tjoelker {
45b1dd83d1SJilles Tjoelker pid_t parent, child, grandchild, pid;
46b1dd83d1SJilles Tjoelker int status, r;
47b1dd83d1SJilles Tjoelker int pip[2];
48b1dd83d1SJilles Tjoelker
49b1dd83d1SJilles Tjoelker /* Be paranoid. */
50b1dd83d1SJilles Tjoelker pid = waitpid(-1, NULL, WNOHANG);
51b1dd83d1SJilles Tjoelker ATF_REQUIRE(pid == -1 && errno == ECHILD);
52b1dd83d1SJilles Tjoelker
53b1dd83d1SJilles Tjoelker parent = getpid();
54b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
55b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
56b1dd83d1SJilles Tjoelker
57b1dd83d1SJilles Tjoelker r = pipe(pip);
58b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
59b1dd83d1SJilles Tjoelker
60b1dd83d1SJilles Tjoelker child = fork();
61b1dd83d1SJilles Tjoelker ATF_REQUIRE(child != -1);
62b1dd83d1SJilles Tjoelker if (child == 0) {
63b1dd83d1SJilles Tjoelker if (close(pip[1]) != 0)
64b1dd83d1SJilles Tjoelker _exit(100);
65b1dd83d1SJilles Tjoelker grandchild = fork();
66b1dd83d1SJilles Tjoelker if (grandchild == -1)
67b1dd83d1SJilles Tjoelker _exit(101);
68b1dd83d1SJilles Tjoelker else if (grandchild == 0) {
69b1dd83d1SJilles Tjoelker if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
70b1dd83d1SJilles Tjoelker _exit(102);
71b1dd83d1SJilles Tjoelker if (getppid() != parent)
72b1dd83d1SJilles Tjoelker _exit(103);
73b1dd83d1SJilles Tjoelker _exit(2);
74b1dd83d1SJilles Tjoelker } else
75b1dd83d1SJilles Tjoelker _exit(3);
76b1dd83d1SJilles Tjoelker }
77b1dd83d1SJilles Tjoelker
78b1dd83d1SJilles Tjoelker pid = waitpid(child, &status, 0);
79b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
80b1dd83d1SJilles Tjoelker r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
81b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(3, r);
82b1dd83d1SJilles Tjoelker
83b1dd83d1SJilles Tjoelker r = close(pip[1]);
84b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
85b1dd83d1SJilles Tjoelker
86b1dd83d1SJilles Tjoelker pid = waitpid(-1, &status, 0);
87b1dd83d1SJilles Tjoelker ATF_REQUIRE(pid > 0 && pid != child);
88b1dd83d1SJilles Tjoelker r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
89b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(2, r);
90b1dd83d1SJilles Tjoelker
91b1dd83d1SJilles Tjoelker r = close(pip[0]);
92b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
93b1dd83d1SJilles Tjoelker }
94b1dd83d1SJilles Tjoelker
95b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_wait_grandchild_first);
ATF_TC_BODY(reaper_wait_grandchild_first,tc)96b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_wait_grandchild_first, tc)
97b1dd83d1SJilles Tjoelker {
98b1dd83d1SJilles Tjoelker pid_t parent, child, grandchild, pid;
99b1dd83d1SJilles Tjoelker int status, r;
100b1dd83d1SJilles Tjoelker
101b1dd83d1SJilles Tjoelker /* Be paranoid. */
102b1dd83d1SJilles Tjoelker pid = waitpid(-1, NULL, WNOHANG);
103b1dd83d1SJilles Tjoelker ATF_REQUIRE(pid == -1 && errno == ECHILD);
104b1dd83d1SJilles Tjoelker
105b1dd83d1SJilles Tjoelker parent = getpid();
106b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
107b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
108b1dd83d1SJilles Tjoelker
109b1dd83d1SJilles Tjoelker child = fork();
110b1dd83d1SJilles Tjoelker ATF_REQUIRE(child != -1);
111b1dd83d1SJilles Tjoelker if (child == 0) {
112b1dd83d1SJilles Tjoelker grandchild = fork();
113b1dd83d1SJilles Tjoelker if (grandchild == -1)
114b1dd83d1SJilles Tjoelker _exit(101);
115b1dd83d1SJilles Tjoelker else if (grandchild == 0)
116b1dd83d1SJilles Tjoelker _exit(2);
117b1dd83d1SJilles Tjoelker else {
118b1dd83d1SJilles Tjoelker if (waitid(P_PID, grandchild, NULL,
119b1dd83d1SJilles Tjoelker WNOWAIT | WEXITED) != 0)
120b1dd83d1SJilles Tjoelker _exit(102);
121b1dd83d1SJilles Tjoelker _exit(3);
122b1dd83d1SJilles Tjoelker }
123b1dd83d1SJilles Tjoelker }
124b1dd83d1SJilles Tjoelker
125b1dd83d1SJilles Tjoelker pid = waitpid(child, &status, 0);
126b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
127b1dd83d1SJilles Tjoelker r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
128b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(3, r);
129b1dd83d1SJilles Tjoelker
130b1dd83d1SJilles Tjoelker pid = waitpid(-1, &status, 0);
131b1dd83d1SJilles Tjoelker ATF_REQUIRE(pid > 0 && pid != child);
132b1dd83d1SJilles Tjoelker r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
133b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(2, r);
134b1dd83d1SJilles Tjoelker }
135b1dd83d1SJilles Tjoelker
136fe56b177SJilles Tjoelker ATF_TC(reaper_sigchld_child_first);
ATF_TC_HEAD(reaper_sigchld_child_first,tc)137fe56b177SJilles Tjoelker ATF_TC_HEAD(reaper_sigchld_child_first, tc)
138fe56b177SJilles Tjoelker {
139fe56b177SJilles Tjoelker atf_tc_set_md_var(tc, "timeout", "2");
140fe56b177SJilles Tjoelker }
ATF_TC_BODY(reaper_sigchld_child_first,tc)141fe56b177SJilles Tjoelker ATF_TC_BODY(reaper_sigchld_child_first, tc)
142fe56b177SJilles Tjoelker {
143fe56b177SJilles Tjoelker struct sigaction act;
144fe56b177SJilles Tjoelker sigset_t mask;
145fe56b177SJilles Tjoelker siginfo_t info;
146fe56b177SJilles Tjoelker pid_t parent, child, grandchild, pid;
147fe56b177SJilles Tjoelker int r;
148fe56b177SJilles Tjoelker int pip[2];
149fe56b177SJilles Tjoelker
150fe56b177SJilles Tjoelker /* Be paranoid. */
151fe56b177SJilles Tjoelker pid = waitpid(-1, NULL, WNOHANG);
152fe56b177SJilles Tjoelker ATF_REQUIRE(pid == -1 && errno == ECHILD);
153fe56b177SJilles Tjoelker
154fe56b177SJilles Tjoelker act.sa_sigaction = dummy_sighandler;
155fe56b177SJilles Tjoelker act.sa_flags = SA_SIGINFO | SA_RESTART;
156fe56b177SJilles Tjoelker r = sigemptyset(&act.sa_mask);
157fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
158fe56b177SJilles Tjoelker r = sigaction(SIGCHLD, &act, NULL);
159fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
160fe56b177SJilles Tjoelker
161fe56b177SJilles Tjoelker r = sigemptyset(&mask);
162fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
163fe56b177SJilles Tjoelker r = sigaddset(&mask, SIGCHLD);
164fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
165fe56b177SJilles Tjoelker r = sigprocmask(SIG_BLOCK, &mask, NULL);
166fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
167fe56b177SJilles Tjoelker
168fe56b177SJilles Tjoelker parent = getpid();
169fe56b177SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
170fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
171fe56b177SJilles Tjoelker
172fe56b177SJilles Tjoelker r = pipe(pip);
173fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
174fe56b177SJilles Tjoelker
175fe56b177SJilles Tjoelker child = fork();
176fe56b177SJilles Tjoelker ATF_REQUIRE(child != -1);
177fe56b177SJilles Tjoelker if (child == 0) {
178fe56b177SJilles Tjoelker if (close(pip[1]) != 0)
179fe56b177SJilles Tjoelker _exit(100);
180fe56b177SJilles Tjoelker grandchild = fork();
181fe56b177SJilles Tjoelker if (grandchild == -1)
182fe56b177SJilles Tjoelker _exit(101);
183fe56b177SJilles Tjoelker else if (grandchild == 0) {
184fe56b177SJilles Tjoelker if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
185fe56b177SJilles Tjoelker _exit(102);
186fe56b177SJilles Tjoelker if (getppid() != parent)
187fe56b177SJilles Tjoelker _exit(103);
188fe56b177SJilles Tjoelker _exit(2);
189fe56b177SJilles Tjoelker } else
190fe56b177SJilles Tjoelker _exit(3);
191fe56b177SJilles Tjoelker }
192fe56b177SJilles Tjoelker
193fe56b177SJilles Tjoelker r = sigwaitinfo(&mask, &info);
194fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(SIGCHLD, r);
195fe56b177SJilles Tjoelker ATF_CHECK_EQ(SIGCHLD, info.si_signo);
196fe56b177SJilles Tjoelker ATF_CHECK_EQ(CLD_EXITED, info.si_code);
197fe56b177SJilles Tjoelker ATF_CHECK_EQ(3, info.si_status);
198fe56b177SJilles Tjoelker ATF_CHECK_EQ(child, info.si_pid);
199fe56b177SJilles Tjoelker
200fe56b177SJilles Tjoelker pid = waitpid(child, NULL, 0);
201fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
202fe56b177SJilles Tjoelker
203fe56b177SJilles Tjoelker r = close(pip[1]);
204fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
205fe56b177SJilles Tjoelker
206fe56b177SJilles Tjoelker r = sigwaitinfo(&mask, &info);
207fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(SIGCHLD, r);
208fe56b177SJilles Tjoelker ATF_CHECK_EQ(SIGCHLD, info.si_signo);
209fe56b177SJilles Tjoelker ATF_CHECK_EQ(CLD_EXITED, info.si_code);
210fe56b177SJilles Tjoelker ATF_CHECK_EQ(2, info.si_status);
211fe56b177SJilles Tjoelker grandchild = info.si_pid;
212fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild > 0);
213fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild != parent);
214fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild != child);
215fe56b177SJilles Tjoelker
216fe56b177SJilles Tjoelker pid = waitpid(-1, NULL, 0);
217fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(grandchild, pid);
218fe56b177SJilles Tjoelker
219fe56b177SJilles Tjoelker r = close(pip[0]);
220fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
221fe56b177SJilles Tjoelker }
222fe56b177SJilles Tjoelker
223fe56b177SJilles Tjoelker ATF_TC(reaper_sigchld_grandchild_first);
ATF_TC_HEAD(reaper_sigchld_grandchild_first,tc)224fe56b177SJilles Tjoelker ATF_TC_HEAD(reaper_sigchld_grandchild_first, tc)
225fe56b177SJilles Tjoelker {
226fe56b177SJilles Tjoelker atf_tc_set_md_var(tc, "timeout", "2");
227fe56b177SJilles Tjoelker }
ATF_TC_BODY(reaper_sigchld_grandchild_first,tc)228fe56b177SJilles Tjoelker ATF_TC_BODY(reaper_sigchld_grandchild_first, tc)
229fe56b177SJilles Tjoelker {
230fe56b177SJilles Tjoelker struct sigaction act;
231fe56b177SJilles Tjoelker sigset_t mask;
232fe56b177SJilles Tjoelker siginfo_t info;
233fe56b177SJilles Tjoelker pid_t parent, child, grandchild, pid;
234fe56b177SJilles Tjoelker int r;
235fe56b177SJilles Tjoelker
236fe56b177SJilles Tjoelker /* Be paranoid. */
237fe56b177SJilles Tjoelker pid = waitpid(-1, NULL, WNOHANG);
238fe56b177SJilles Tjoelker ATF_REQUIRE(pid == -1 && errno == ECHILD);
239fe56b177SJilles Tjoelker
240fe56b177SJilles Tjoelker act.sa_sigaction = dummy_sighandler;
241fe56b177SJilles Tjoelker act.sa_flags = SA_SIGINFO | SA_RESTART;
242fe56b177SJilles Tjoelker r = sigemptyset(&act.sa_mask);
243fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
244fe56b177SJilles Tjoelker r = sigaction(SIGCHLD, &act, NULL);
245fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
246fe56b177SJilles Tjoelker
247fe56b177SJilles Tjoelker r = sigemptyset(&mask);
248fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
249fe56b177SJilles Tjoelker r = sigaddset(&mask, SIGCHLD);
250fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
251fe56b177SJilles Tjoelker r = sigprocmask(SIG_BLOCK, &mask, NULL);
252fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
253fe56b177SJilles Tjoelker
254fe56b177SJilles Tjoelker parent = getpid();
255fe56b177SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
256fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
257fe56b177SJilles Tjoelker
258fe56b177SJilles Tjoelker child = fork();
259fe56b177SJilles Tjoelker ATF_REQUIRE(child != -1);
260fe56b177SJilles Tjoelker if (child == 0) {
261fe56b177SJilles Tjoelker grandchild = fork();
262fe56b177SJilles Tjoelker if (grandchild == -1)
263fe56b177SJilles Tjoelker _exit(101);
264fe56b177SJilles Tjoelker else if (grandchild == 0)
265fe56b177SJilles Tjoelker _exit(2);
266fe56b177SJilles Tjoelker else {
267fe56b177SJilles Tjoelker if (waitid(P_PID, grandchild, NULL,
268fe56b177SJilles Tjoelker WNOWAIT | WEXITED) != 0)
269fe56b177SJilles Tjoelker _exit(102);
270fe56b177SJilles Tjoelker _exit(3);
271fe56b177SJilles Tjoelker }
272fe56b177SJilles Tjoelker }
273fe56b177SJilles Tjoelker
274fe56b177SJilles Tjoelker pid = waitpid(child, NULL, 0);
275fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
276fe56b177SJilles Tjoelker
277fe56b177SJilles Tjoelker r = sigwaitinfo(&mask, &info);
278fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(SIGCHLD, r);
279fe56b177SJilles Tjoelker ATF_CHECK_EQ(SIGCHLD, info.si_signo);
280fe56b177SJilles Tjoelker ATF_CHECK_EQ(CLD_EXITED, info.si_code);
281fe56b177SJilles Tjoelker ATF_CHECK_EQ(2, info.si_status);
282fe56b177SJilles Tjoelker grandchild = info.si_pid;
283fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild > 0);
284fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild != parent);
285fe56b177SJilles Tjoelker ATF_REQUIRE(grandchild != child);
286fe56b177SJilles Tjoelker
287fe56b177SJilles Tjoelker pid = waitpid(-1, NULL, 0);
288fe56b177SJilles Tjoelker ATF_REQUIRE_EQ(grandchild, pid);
289fe56b177SJilles Tjoelker }
290fe56b177SJilles Tjoelker
291b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_status);
ATF_TC_BODY(reaper_status,tc)292b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_status, tc)
293b1dd83d1SJilles Tjoelker {
294b1dd83d1SJilles Tjoelker struct procctl_reaper_status st;
295b1dd83d1SJilles Tjoelker ssize_t sr;
296b1dd83d1SJilles Tjoelker pid_t parent, child, pid;
297b1dd83d1SJilles Tjoelker int r, status;
298b1dd83d1SJilles Tjoelker int pip[2];
299b1dd83d1SJilles Tjoelker
300b1dd83d1SJilles Tjoelker parent = getpid();
301b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
302b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
303b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, st.rs_flags & REAPER_STATUS_OWNED);
304b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_children > 0);
305b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_descendants > 0);
306b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_descendants >= st.rs_children);
307b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper != parent);
308b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper > 0);
309b1dd83d1SJilles Tjoelker
310b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
311b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
312b1dd83d1SJilles Tjoelker
313b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
314b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
315b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_STATUS_OWNED,
316b1dd83d1SJilles Tjoelker st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
317b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, st.rs_children);
318b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, st.rs_descendants);
319b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper == parent);
320b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(-1, st.rs_pid);
321b1dd83d1SJilles Tjoelker
322b1dd83d1SJilles Tjoelker r = pipe(pip);
323b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
324b1dd83d1SJilles Tjoelker child = fork();
325b1dd83d1SJilles Tjoelker ATF_REQUIRE(child != -1);
326b1dd83d1SJilles Tjoelker if (child == 0) {
327b1dd83d1SJilles Tjoelker if (close(pip[0]) != 0)
328b1dd83d1SJilles Tjoelker _exit(100);
329b1dd83d1SJilles Tjoelker if (procctl(P_PID, parent, PROC_REAP_STATUS, &st) != 0)
330b1dd83d1SJilles Tjoelker _exit(101);
331b1dd83d1SJilles Tjoelker if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
332b1dd83d1SJilles Tjoelker _exit(102);
333b1dd83d1SJilles Tjoelker if (procctl(P_PID, getpid(), PROC_REAP_STATUS, &st) != 0)
334b1dd83d1SJilles Tjoelker _exit(103);
335b1dd83d1SJilles Tjoelker if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
336b1dd83d1SJilles Tjoelker _exit(104);
337b1dd83d1SJilles Tjoelker _exit(0);
338b1dd83d1SJilles Tjoelker }
339b1dd83d1SJilles Tjoelker r = close(pip[1]);
340b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
341b1dd83d1SJilles Tjoelker
342b1dd83d1SJilles Tjoelker sr = read(pip[0], &st, sizeof(st));
343b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
344b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_STATUS_OWNED,
345b1dd83d1SJilles Tjoelker st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
346b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(1, st.rs_children);
347b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(1, st.rs_descendants);
348b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper == parent);
349b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, st.rs_pid);
350b1dd83d1SJilles Tjoelker sr = read(pip[0], &st, sizeof(st));
351b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ((ssize_t)sizeof(st), sr);
352b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0,
353b1dd83d1SJilles Tjoelker st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
354b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(1, st.rs_children);
355b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(1, st.rs_descendants);
356b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper == parent);
357b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, st.rs_pid);
358b1dd83d1SJilles Tjoelker
359b1dd83d1SJilles Tjoelker r = close(pip[0]);
360b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
361b1dd83d1SJilles Tjoelker pid = waitpid(child, &status, 0);
362b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
363b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, status);
364b1dd83d1SJilles Tjoelker
365b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
366b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
367b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_STATUS_OWNED,
368b1dd83d1SJilles Tjoelker st.rs_flags & (REAPER_STATUS_OWNED | REAPER_STATUS_REALINIT));
369b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, st.rs_children);
370b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, st.rs_descendants);
371b1dd83d1SJilles Tjoelker ATF_CHECK(st.rs_reaper == parent);
372b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(-1, st.rs_pid);
373b1dd83d1SJilles Tjoelker }
374b1dd83d1SJilles Tjoelker
375b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_getpids);
ATF_TC_BODY(reaper_getpids,tc)376b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_getpids, tc)
377b1dd83d1SJilles Tjoelker {
378b1dd83d1SJilles Tjoelker struct procctl_reaper_pidinfo info[10];
379b1dd83d1SJilles Tjoelker ssize_t sr;
380b1dd83d1SJilles Tjoelker pid_t parent, child, grandchild, pid;
381b1dd83d1SJilles Tjoelker int r, status, childidx;
382b1dd83d1SJilles Tjoelker int pipa[2], pipb[2];
383b1dd83d1SJilles Tjoelker
384b1dd83d1SJilles Tjoelker parent = getpid();
385b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
386b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
387b1dd83d1SJilles Tjoelker
388b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
389b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
390b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
391b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
392b1dd83d1SJilles Tjoelker .rp_pids = info
393b1dd83d1SJilles Tjoelker });
394b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
395b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
396b1dd83d1SJilles Tjoelker
397b1dd83d1SJilles Tjoelker r = pipe(pipa);
398b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
399b1dd83d1SJilles Tjoelker r = pipe(pipb);
400b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
401b1dd83d1SJilles Tjoelker child = fork();
402b1dd83d1SJilles Tjoelker ATF_REQUIRE(child != -1);
403b1dd83d1SJilles Tjoelker if (child == 0) {
404b1dd83d1SJilles Tjoelker if (close(pipa[1]) != 0)
405b1dd83d1SJilles Tjoelker _exit(100);
406b1dd83d1SJilles Tjoelker if (close(pipb[0]) != 0)
407b1dd83d1SJilles Tjoelker _exit(100);
408b1dd83d1SJilles Tjoelker if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
409b1dd83d1SJilles Tjoelker _exit(101);
410b1dd83d1SJilles Tjoelker grandchild = fork();
411b1dd83d1SJilles Tjoelker if (grandchild == -1)
412b1dd83d1SJilles Tjoelker _exit(102);
413b1dd83d1SJilles Tjoelker if (grandchild == 0) {
414b1dd83d1SJilles Tjoelker if (write(pipb[1], &(uint8_t){ 0 }, 1) != 1)
415b1dd83d1SJilles Tjoelker _exit(103);
416b1dd83d1SJilles Tjoelker if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
417b1dd83d1SJilles Tjoelker _exit(104);
418b1dd83d1SJilles Tjoelker _exit(0);
419b1dd83d1SJilles Tjoelker }
420b1dd83d1SJilles Tjoelker for (;;)
421b1dd83d1SJilles Tjoelker pause();
422b1dd83d1SJilles Tjoelker }
423b1dd83d1SJilles Tjoelker r = close(pipa[0]);
424b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
425b1dd83d1SJilles Tjoelker r = close(pipb[1]);
426b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
427b1dd83d1SJilles Tjoelker
428b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
429b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
430b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
431b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
432b1dd83d1SJilles Tjoelker .rp_pids = info
433b1dd83d1SJilles Tjoelker });
434b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
435b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD,
436b1dd83d1SJilles Tjoelker info[0].pi_flags & (REAPER_PIDINFO_VALID | REAPER_PIDINFO_CHILD));
437b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[0].pi_pid);
438b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[0].pi_subtree);
439b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
440b1dd83d1SJilles Tjoelker
441b1dd83d1SJilles Tjoelker sr = write(pipa[1], &(uint8_t){ 0 }, 1);
442b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
443b1dd83d1SJilles Tjoelker sr = read(pipb[0], &(uint8_t){ 0 }, 1);
444b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
445b1dd83d1SJilles Tjoelker
446b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
447b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
448b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
449b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
450b1dd83d1SJilles Tjoelker .rp_pids = info
451b1dd83d1SJilles Tjoelker });
452b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
453b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
454b1dd83d1SJilles Tjoelker info[0].pi_flags & REAPER_PIDINFO_VALID);
455b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
456b1dd83d1SJilles Tjoelker info[1].pi_flags & REAPER_PIDINFO_VALID);
457b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[2].pi_flags & REAPER_PIDINFO_VALID);
458b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[0].pi_subtree);
459b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[1].pi_subtree);
460b1dd83d1SJilles Tjoelker childidx = info[1].pi_pid == child ? 1 : 0;
461b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
462b1dd83d1SJilles Tjoelker info[childidx].pi_flags & REAPER_PIDINFO_CHILD);
463b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[childidx ^ 1].pi_flags & REAPER_PIDINFO_CHILD);
464b1dd83d1SJilles Tjoelker ATF_CHECK(info[childidx].pi_pid == child);
465b1dd83d1SJilles Tjoelker grandchild = info[childidx ^ 1].pi_pid;
466b1dd83d1SJilles Tjoelker ATF_CHECK(grandchild > 0);
467b1dd83d1SJilles Tjoelker ATF_CHECK(grandchild != child);
468b1dd83d1SJilles Tjoelker ATF_CHECK(grandchild != parent);
469b1dd83d1SJilles Tjoelker
470b1dd83d1SJilles Tjoelker r = kill(child, SIGTERM);
471b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
472b1dd83d1SJilles Tjoelker
473b1dd83d1SJilles Tjoelker pid = waitpid(child, &status, 0);
474b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
475b1dd83d1SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
476b1dd83d1SJilles Tjoelker
477b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
478b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
479b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
480b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
481b1dd83d1SJilles Tjoelker .rp_pids = info
482b1dd83d1SJilles Tjoelker });
483b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
484b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
485b1dd83d1SJilles Tjoelker info[0].pi_flags & REAPER_PIDINFO_VALID);
486b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
487b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[0].pi_subtree);
488b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
489b1dd83d1SJilles Tjoelker info[0].pi_flags & REAPER_PIDINFO_CHILD);
490b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(grandchild, info[0].pi_pid);
491b1dd83d1SJilles Tjoelker
492b1dd83d1SJilles Tjoelker sr = write(pipa[1], &(uint8_t){ 0 }, 1);
493b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
494b1dd83d1SJilles Tjoelker
495b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
496b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
497b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
498b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
499b1dd83d1SJilles Tjoelker .rp_pids = info
500b1dd83d1SJilles Tjoelker });
501b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
502b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_VALID,
503b1dd83d1SJilles Tjoelker info[0].pi_flags & REAPER_PIDINFO_VALID);
504b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[1].pi_flags & REAPER_PIDINFO_VALID);
505b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(child, info[0].pi_subtree);
506b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(REAPER_PIDINFO_CHILD,
507b1dd83d1SJilles Tjoelker info[0].pi_flags & REAPER_PIDINFO_CHILD);
508b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(grandchild, info[0].pi_pid);
509b1dd83d1SJilles Tjoelker
510b1dd83d1SJilles Tjoelker pid = waitpid(grandchild, &status, 0);
511b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(grandchild, pid);
512b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, status);
513b1dd83d1SJilles Tjoelker
514b1dd83d1SJilles Tjoelker memset(info, '\0', sizeof(info));
515b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_GETPIDS,
516b1dd83d1SJilles Tjoelker &(struct procctl_reaper_pids){
517b1dd83d1SJilles Tjoelker .rp_count = sizeof(info) / sizeof(info[0]),
518b1dd83d1SJilles Tjoelker .rp_pids = info
519b1dd83d1SJilles Tjoelker });
520b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
521b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
522b1dd83d1SJilles Tjoelker
523b1dd83d1SJilles Tjoelker r = close(pipa[1]);
524b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
525b1dd83d1SJilles Tjoelker r = close(pipb[0]);
526b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
527b1dd83d1SJilles Tjoelker }
528b1dd83d1SJilles Tjoelker
529b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_kill_badsig);
ATF_TC_BODY(reaper_kill_badsig,tc)530b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_kill_badsig, tc)
531b1dd83d1SJilles Tjoelker {
532b1dd83d1SJilles Tjoelker struct procctl_reaper_kill params;
533b1dd83d1SJilles Tjoelker pid_t parent;
534b1dd83d1SJilles Tjoelker int r;
535b1dd83d1SJilles Tjoelker
536b1dd83d1SJilles Tjoelker parent = getpid();
537b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
538b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
539b1dd83d1SJilles Tjoelker
540b1dd83d1SJilles Tjoelker params.rk_sig = -1;
541b1dd83d1SJilles Tjoelker params.rk_flags = 0;
542b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
543b1dd83d1SJilles Tjoelker ATF_CHECK(r == -1 && errno == EINVAL);
544b1dd83d1SJilles Tjoelker }
545b1dd83d1SJilles Tjoelker
546b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_kill_sigzero);
ATF_TC_BODY(reaper_kill_sigzero,tc)547b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_kill_sigzero, tc)
548b1dd83d1SJilles Tjoelker {
549b1dd83d1SJilles Tjoelker struct procctl_reaper_kill params;
550b1dd83d1SJilles Tjoelker pid_t parent;
551b1dd83d1SJilles Tjoelker int r;
552b1dd83d1SJilles Tjoelker
553b1dd83d1SJilles Tjoelker parent = getpid();
554b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
555b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
556b1dd83d1SJilles Tjoelker
557b1dd83d1SJilles Tjoelker params.rk_sig = 0;
558b1dd83d1SJilles Tjoelker params.rk_flags = 0;
559b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
560b1dd83d1SJilles Tjoelker ATF_CHECK(r == -1 && errno == EINVAL);
561b1dd83d1SJilles Tjoelker }
562b1dd83d1SJilles Tjoelker
563b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_kill_empty);
ATF_TC_BODY(reaper_kill_empty,tc)564b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_kill_empty, tc)
565b1dd83d1SJilles Tjoelker {
566b1dd83d1SJilles Tjoelker struct procctl_reaper_kill params;
567b1dd83d1SJilles Tjoelker pid_t parent;
568b1dd83d1SJilles Tjoelker int r;
569b1dd83d1SJilles Tjoelker
570b1dd83d1SJilles Tjoelker parent = getpid();
571b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
572b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
573b1dd83d1SJilles Tjoelker
574b1dd83d1SJilles Tjoelker params.rk_sig = SIGTERM;
575b1dd83d1SJilles Tjoelker params.rk_flags = 0;
576b1dd83d1SJilles Tjoelker params.rk_killed = 77;
577b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
578b1dd83d1SJilles Tjoelker ATF_CHECK(r == -1 && errno == ESRCH);
579b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, params.rk_killed);
580b1dd83d1SJilles Tjoelker }
581b1dd83d1SJilles Tjoelker
582b1dd83d1SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_kill_normal);
ATF_TC_BODY(reaper_kill_normal,tc)583b1dd83d1SJilles Tjoelker ATF_TC_BODY(reaper_kill_normal, tc)
584b1dd83d1SJilles Tjoelker {
585b1dd83d1SJilles Tjoelker struct procctl_reaper_kill params;
586b1dd83d1SJilles Tjoelker ssize_t sr;
587b1dd83d1SJilles Tjoelker pid_t parent, child, grandchild, pid;
588b1dd83d1SJilles Tjoelker int r, status;
589b1dd83d1SJilles Tjoelker int pip[2];
590b1dd83d1SJilles Tjoelker
591b1dd83d1SJilles Tjoelker parent = getpid();
592b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
593b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
594b1dd83d1SJilles Tjoelker
595b1dd83d1SJilles Tjoelker r = pipe(pip);
596b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
597b1dd83d1SJilles Tjoelker child = fork();
598b1dd83d1SJilles Tjoelker ATF_REQUIRE(child != -1);
599b1dd83d1SJilles Tjoelker if (child == 0) {
600b1dd83d1SJilles Tjoelker if (close(pip[0]) != 0)
601b1dd83d1SJilles Tjoelker _exit(100);
602b1dd83d1SJilles Tjoelker grandchild = fork();
603b1dd83d1SJilles Tjoelker if (grandchild == -1)
604b1dd83d1SJilles Tjoelker _exit(101);
605b1dd83d1SJilles Tjoelker if (grandchild == 0) {
606b1dd83d1SJilles Tjoelker if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
607b1dd83d1SJilles Tjoelker _exit(102);
608b1dd83d1SJilles Tjoelker for (;;)
609b1dd83d1SJilles Tjoelker pause();
610b1dd83d1SJilles Tjoelker }
611b1dd83d1SJilles Tjoelker for (;;)
612b1dd83d1SJilles Tjoelker pause();
613b1dd83d1SJilles Tjoelker }
614b1dd83d1SJilles Tjoelker r = close(pip[1]);
615b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
616b1dd83d1SJilles Tjoelker
617b1dd83d1SJilles Tjoelker sr = read(pip[0], &(uint8_t){ 0 }, 1);
618b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
619b1dd83d1SJilles Tjoelker
620b1dd83d1SJilles Tjoelker params.rk_sig = SIGTERM;
621b1dd83d1SJilles Tjoelker params.rk_flags = 0;
622b1dd83d1SJilles Tjoelker params.rk_killed = 77;
623b1dd83d1SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
624b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(0, r);
625b1dd83d1SJilles Tjoelker ATF_CHECK_EQ(2, params.rk_killed);
626b1dd83d1SJilles Tjoelker
627b1dd83d1SJilles Tjoelker pid = waitpid(child, &status, 0);
628b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(child, pid);
629b1dd83d1SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
630b1dd83d1SJilles Tjoelker
631b1dd83d1SJilles Tjoelker pid = waitpid(-1, &status, 0);
632b1dd83d1SJilles Tjoelker ATF_REQUIRE(pid > 0);
633b1dd83d1SJilles Tjoelker ATF_CHECK(pid != parent);
634b1dd83d1SJilles Tjoelker ATF_CHECK(pid != child);
635b1dd83d1SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
636b1dd83d1SJilles Tjoelker
637b1dd83d1SJilles Tjoelker r = close(pip[0]);
638b1dd83d1SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
639b1dd83d1SJilles Tjoelker }
640b1dd83d1SJilles Tjoelker
641b9a6fb93SJilles Tjoelker ATF_TC_WITHOUT_HEAD(reaper_kill_subtree);
ATF_TC_BODY(reaper_kill_subtree,tc)642b9a6fb93SJilles Tjoelker ATF_TC_BODY(reaper_kill_subtree, tc)
643b9a6fb93SJilles Tjoelker {
644b9a6fb93SJilles Tjoelker struct procctl_reaper_kill params;
645b9a6fb93SJilles Tjoelker ssize_t sr;
646b9a6fb93SJilles Tjoelker pid_t parent, child1, child2, grandchild1, grandchild2, pid;
647b9a6fb93SJilles Tjoelker int r, status;
648b9a6fb93SJilles Tjoelker int pip[2];
649b9a6fb93SJilles Tjoelker
650b9a6fb93SJilles Tjoelker parent = getpid();
651b9a6fb93SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
652b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
653b9a6fb93SJilles Tjoelker
654b9a6fb93SJilles Tjoelker r = pipe(pip);
655b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
656b9a6fb93SJilles Tjoelker child1 = fork();
657b9a6fb93SJilles Tjoelker ATF_REQUIRE(child1 != -1);
658b9a6fb93SJilles Tjoelker if (child1 == 0) {
659b9a6fb93SJilles Tjoelker if (close(pip[0]) != 0)
660b9a6fb93SJilles Tjoelker _exit(100);
661b9a6fb93SJilles Tjoelker grandchild1 = fork();
662b9a6fb93SJilles Tjoelker if (grandchild1 == -1)
663b9a6fb93SJilles Tjoelker _exit(101);
664b9a6fb93SJilles Tjoelker if (grandchild1 == 0) {
665b9a6fb93SJilles Tjoelker if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
666b9a6fb93SJilles Tjoelker _exit(102);
667b9a6fb93SJilles Tjoelker for (;;)
668b9a6fb93SJilles Tjoelker pause();
669b9a6fb93SJilles Tjoelker }
670b9a6fb93SJilles Tjoelker for (;;)
671b9a6fb93SJilles Tjoelker pause();
672b9a6fb93SJilles Tjoelker }
673b9a6fb93SJilles Tjoelker child2 = fork();
674b9a6fb93SJilles Tjoelker ATF_REQUIRE(child2 != -1);
675b9a6fb93SJilles Tjoelker if (child2 == 0) {
676b9a6fb93SJilles Tjoelker if (close(pip[0]) != 0)
677b9a6fb93SJilles Tjoelker _exit(100);
678b9a6fb93SJilles Tjoelker grandchild2 = fork();
679b9a6fb93SJilles Tjoelker if (grandchild2 == -1)
680b9a6fb93SJilles Tjoelker _exit(101);
681b9a6fb93SJilles Tjoelker if (grandchild2 == 0) {
682b9a6fb93SJilles Tjoelker if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
683b9a6fb93SJilles Tjoelker _exit(102);
684b9a6fb93SJilles Tjoelker for (;;)
685b9a6fb93SJilles Tjoelker pause();
686b9a6fb93SJilles Tjoelker }
687b9a6fb93SJilles Tjoelker for (;;)
688b9a6fb93SJilles Tjoelker pause();
689b9a6fb93SJilles Tjoelker }
690b9a6fb93SJilles Tjoelker r = close(pip[1]);
691b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
692b9a6fb93SJilles Tjoelker
693b9a6fb93SJilles Tjoelker sr = read(pip[0], &(uint8_t){ 0 }, 1);
694b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
695b9a6fb93SJilles Tjoelker sr = read(pip[0], &(uint8_t){ 0 }, 1);
696b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(1, sr);
697b9a6fb93SJilles Tjoelker
698b9a6fb93SJilles Tjoelker params.rk_sig = SIGUSR1;
699b9a6fb93SJilles Tjoelker params.rk_flags = REAPER_KILL_SUBTREE;
700b9a6fb93SJilles Tjoelker params.rk_subtree = child1;
701b9a6fb93SJilles Tjoelker params.rk_killed = 77;
702b9a6fb93SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
703b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
704b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(2, params.rk_killed);
705b9a6fb93SJilles Tjoelker ATF_CHECK_EQ(-1, params.rk_fpid);
706b9a6fb93SJilles Tjoelker
707b9a6fb93SJilles Tjoelker pid = waitpid(child1, &status, 0);
708b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(child1, pid);
709b9a6fb93SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR1);
710b9a6fb93SJilles Tjoelker
711b9a6fb93SJilles Tjoelker pid = waitpid(-1, &status, 0);
712b9a6fb93SJilles Tjoelker ATF_REQUIRE(pid > 0);
713b9a6fb93SJilles Tjoelker ATF_CHECK(pid != parent);
714b9a6fb93SJilles Tjoelker ATF_CHECK(pid != child1);
715b9a6fb93SJilles Tjoelker ATF_CHECK(pid != child2);
716b9a6fb93SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR1);
717b9a6fb93SJilles Tjoelker
718b9a6fb93SJilles Tjoelker params.rk_sig = SIGUSR2;
719b9a6fb93SJilles Tjoelker params.rk_flags = REAPER_KILL_SUBTREE;
720b9a6fb93SJilles Tjoelker params.rk_subtree = child2;
721b9a6fb93SJilles Tjoelker params.rk_killed = 77;
722b9a6fb93SJilles Tjoelker r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
723b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
724b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(2, params.rk_killed);
725b9a6fb93SJilles Tjoelker ATF_CHECK_EQ(-1, params.rk_fpid);
726b9a6fb93SJilles Tjoelker
727b9a6fb93SJilles Tjoelker pid = waitpid(child2, &status, 0);
728b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(child2, pid);
729b9a6fb93SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR2);
730b9a6fb93SJilles Tjoelker
731b9a6fb93SJilles Tjoelker pid = waitpid(-1, &status, 0);
732b9a6fb93SJilles Tjoelker ATF_REQUIRE(pid > 0);
733b9a6fb93SJilles Tjoelker ATF_CHECK(pid != parent);
734b9a6fb93SJilles Tjoelker ATF_CHECK(pid != child1);
735b9a6fb93SJilles Tjoelker ATF_CHECK(pid != child2);
736b9a6fb93SJilles Tjoelker ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR2);
737b9a6fb93SJilles Tjoelker
738b9a6fb93SJilles Tjoelker r = close(pip[0]);
739b9a6fb93SJilles Tjoelker ATF_REQUIRE_EQ(0, r);
740b9a6fb93SJilles Tjoelker }
741b9a6fb93SJilles Tjoelker
742*ddab8c35SMark Johnston ATF_TC_WITHOUT_HEAD(reaper_pdfork);
ATF_TC_BODY(reaper_pdfork,tc)743*ddab8c35SMark Johnston ATF_TC_BODY(reaper_pdfork, tc)
744*ddab8c35SMark Johnston {
745*ddab8c35SMark Johnston struct procctl_reaper_status st;
746*ddab8c35SMark Johnston pid_t child, grandchild, parent, pid;
747*ddab8c35SMark Johnston int pd, r, status;
748*ddab8c35SMark Johnston
749*ddab8c35SMark Johnston parent = getpid();
750*ddab8c35SMark Johnston r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
751*ddab8c35SMark Johnston ATF_REQUIRE_EQ(r, 0);
752*ddab8c35SMark Johnston
753*ddab8c35SMark Johnston child = pdfork(&pd, 0);
754*ddab8c35SMark Johnston ATF_REQUIRE(child != -1);
755*ddab8c35SMark Johnston if (child == 0) {
756*ddab8c35SMark Johnston grandchild = pdfork(&pd, 0);
757*ddab8c35SMark Johnston if (grandchild == -1)
758*ddab8c35SMark Johnston _exit(1);
759*ddab8c35SMark Johnston if (grandchild == 0)
760*ddab8c35SMark Johnston pause();
761*ddab8c35SMark Johnston _exit(0);
762*ddab8c35SMark Johnston }
763*ddab8c35SMark Johnston pid = waitpid(child, &status, 0);
764*ddab8c35SMark Johnston ATF_REQUIRE_EQ(pid, child);
765*ddab8c35SMark Johnston r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
766*ddab8c35SMark Johnston ATF_REQUIRE_EQ(r, 0);
767*ddab8c35SMark Johnston
768*ddab8c35SMark Johnston r = procctl(P_PID, parent, PROC_REAP_STATUS, &st);
769*ddab8c35SMark Johnston ATF_REQUIRE_EQ(r, 0);
770*ddab8c35SMark Johnston ATF_CHECK((st.rs_flags & REAPER_STATUS_OWNED) != 0);
771*ddab8c35SMark Johnston ATF_CHECK(st.rs_reaper == parent);
772*ddab8c35SMark Johnston ATF_CHECK(st.rs_children == 1);
773*ddab8c35SMark Johnston ATF_CHECK(st.rs_descendants == 1);
774*ddab8c35SMark Johnston }
775*ddab8c35SMark Johnston
ATF_TP_ADD_TCS(tp)776b1dd83d1SJilles Tjoelker ATF_TP_ADD_TCS(tp)
777b1dd83d1SJilles Tjoelker {
778b1dd83d1SJilles Tjoelker
779b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_wait_child_first);
780b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_wait_grandchild_first);
781fe56b177SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_sigchld_child_first);
782fe56b177SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_sigchld_grandchild_first);
783b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_status);
784b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_getpids);
785b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_kill_badsig);
786b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_kill_sigzero);
787b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_kill_empty);
788b1dd83d1SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_kill_normal);
789b9a6fb93SJilles Tjoelker ATF_TP_ADD_TC(tp, reaper_kill_subtree);
790*ddab8c35SMark Johnston ATF_TP_ADD_TC(tp, reaper_pdfork);
791b1dd83d1SJilles Tjoelker return (atf_no_error());
792b1dd83d1SJilles Tjoelker }
793