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