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