2 * Copyright (c) 2016 Jilles Tjoelker
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 #include <sys/procctl.h>
29 #include <sys/procdesc.h>
38 dummy_sighandler(int sig __unused, siginfo_t *info __unused, void *ctx __unused)
42 ATF_TC_WITHOUT_HEAD(reaper_wait_child_first);
43 ATF_TC_BODY(reaper_wait_child_first, tc)
45 pid_t parent, child, grandchild, pid;
50 pid = waitpid(-1, NULL, WNOHANG);
51 ATF_REQUIRE(pid == -1 && errno == ECHILD);
54 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
61 ATF_REQUIRE(child != -1);
63 if (close(pip[1]) != 0)
68 else if (grandchild == 0) {
69 if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
71 if (getppid() != parent)
78 pid = waitpid(child, &status, 0);
79 ATF_REQUIRE_EQ(child, pid);
80 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
86 pid = waitpid(-1, &status, 0);
87 ATF_REQUIRE(pid > 0 && pid != child);
88 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
95 ATF_TC_WITHOUT_HEAD(reaper_wait_grandchild_first);
96 ATF_TC_BODY(reaper_wait_grandchild_first, tc)
98 pid_t parent, child, grandchild, pid;
102 pid = waitpid(-1, NULL, WNOHANG);
103 ATF_REQUIRE(pid == -1 && errno == ECHILD);
106 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
107 ATF_REQUIRE_EQ(0, r);
110 ATF_REQUIRE(child != -1);
113 if (grandchild == -1)
115 else if (grandchild == 0)
118 if (waitid(P_PID, grandchild, NULL,
119 WNOWAIT | WEXITED) != 0)
125 pid = waitpid(child, &status, 0);
126 ATF_REQUIRE_EQ(child, pid);
127 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
130 pid = waitpid(-1, &status, 0);
131 ATF_REQUIRE(pid > 0 && pid != child);
132 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
136 ATF_TC(reaper_sigchld_child_first);
137 ATF_TC_HEAD(reaper_sigchld_child_first, tc)
139 atf_tc_set_md_var(tc, "timeout", "2");
141 ATF_TC_BODY(reaper_sigchld_child_first, tc)
143 struct sigaction act;
146 pid_t parent, child, grandchild, pid;
151 pid = waitpid(-1, NULL, WNOHANG);
152 ATF_REQUIRE(pid == -1 && errno == ECHILD);
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);
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);
169 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
170 ATF_REQUIRE_EQ(0, r);
173 ATF_REQUIRE_EQ(0, r);
176 ATF_REQUIRE(child != -1);
178 if (close(pip[1]) != 0)
181 if (grandchild == -1)
183 else if (grandchild == 0) {
184 if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
186 if (getppid() != parent)
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);
200 pid = waitpid(child, NULL, 0);
201 ATF_REQUIRE_EQ(child, pid);
204 ATF_REQUIRE_EQ(0, r);
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);
216 pid = waitpid(-1, NULL, 0);
217 ATF_REQUIRE_EQ(grandchild, pid);
220 ATF_REQUIRE_EQ(0, r);
223 ATF_TC(reaper_sigchld_grandchild_first);
224 ATF_TC_HEAD(reaper_sigchld_grandchild_first, tc)
226 atf_tc_set_md_var(tc, "timeout", "2");
228 ATF_TC_BODY(reaper_sigchld_grandchild_first, tc)
230 struct sigaction act;
233 pid_t parent, child, grandchild, pid;
237 pid = waitpid(-1, NULL, WNOHANG);
238 ATF_REQUIRE(pid == -1 && errno == ECHILD);
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);
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);
255 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
256 ATF_REQUIRE_EQ(0, r);
259 ATF_REQUIRE(child != -1);
262 if (grandchild == -1)
264 else if (grandchild == 0)
267 if (waitid(P_PID, grandchild, NULL,
268 WNOWAIT | WEXITED) != 0)
274 pid = waitpid(child, NULL, 0);
275 ATF_REQUIRE_EQ(child, pid);
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);
287 pid = waitpid(-1, NULL, 0);
288 ATF_REQUIRE_EQ(grandchild, pid);
291 ATF_TC_WITHOUT_HEAD(reaper_status);
292 ATF_TC_BODY(reaper_status, tc)
294 struct procctl_reaper_status st;
296 pid_t parent, child, pid;
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);
310 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
311 ATF_REQUIRE_EQ(0, r);
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);
323 ATF_REQUIRE_EQ(0, r);
325 ATF_REQUIRE(child != -1);
327 if (close(pip[0]) != 0)
329 if (procctl(P_PID, parent, PROC_REAP_STATUS, &st) != 0)
331 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
333 if (procctl(P_PID, getpid(), PROC_REAP_STATUS, &st) != 0)
335 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
340 ATF_REQUIRE_EQ(0, r);
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);
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);
360 ATF_REQUIRE_EQ(0, r);
361 pid = waitpid(child, &status, 0);
362 ATF_REQUIRE_EQ(child, pid);
363 ATF_CHECK_EQ(0, status);
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);
375 ATF_TC_WITHOUT_HEAD(reaper_getpids);
376 ATF_TC_BODY(reaper_getpids, tc)
378 struct procctl_reaper_pidinfo info[10];
380 pid_t parent, child, grandchild, pid;
381 int r, status, childidx;
382 int pipa[2], pipb[2];
385 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
386 ATF_REQUIRE_EQ(0, r);
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]),
395 ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
398 ATF_REQUIRE_EQ(0, r);
400 ATF_REQUIRE_EQ(0, r);
402 ATF_REQUIRE(child != -1);
404 if (close(pipa[1]) != 0)
406 if (close(pipb[0]) != 0)
408 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
411 if (grandchild == -1)
413 if (grandchild == 0) {
414 if (write(pipb[1], &(uint8_t){ 0 }, 1) != 1)
416 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
424 ATF_REQUIRE_EQ(0, r);
426 ATF_REQUIRE_EQ(0, r);
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]),
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);
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);
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]),
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);
470 r = kill(child, SIGTERM);
471 ATF_REQUIRE_EQ(0, r);
473 pid = waitpid(child, &status, 0);
474 ATF_REQUIRE_EQ(child, pid);
475 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
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]),
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);
492 sr = write(pipa[1], &(uint8_t){ 0 }, 1);
493 ATF_REQUIRE_EQ(1, sr);
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]),
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);
510 pid = waitpid(grandchild, &status, 0);
511 ATF_REQUIRE_EQ(grandchild, pid);
512 ATF_CHECK_EQ(0, status);
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]),
521 ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
524 ATF_REQUIRE_EQ(0, r);
526 ATF_REQUIRE_EQ(0, r);
529 ATF_TC_WITHOUT_HEAD(reaper_kill_badsig);
530 ATF_TC_BODY(reaper_kill_badsig, tc)
532 struct procctl_reaper_kill params;
537 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
538 ATF_REQUIRE_EQ(0, r);
542 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
543 ATF_CHECK(r == -1 && errno == EINVAL);
546 ATF_TC_WITHOUT_HEAD(reaper_kill_sigzero);
547 ATF_TC_BODY(reaper_kill_sigzero, tc)
549 struct procctl_reaper_kill params;
554 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
555 ATF_REQUIRE_EQ(0, r);
559 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
560 ATF_CHECK(r == -1 && errno == EINVAL);
563 ATF_TC_WITHOUT_HEAD(reaper_kill_empty);
564 ATF_TC_BODY(reaper_kill_empty, tc)
566 struct procctl_reaper_kill params;
571 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
572 ATF_REQUIRE_EQ(0, r);
574 params.rk_sig = SIGTERM;
576 params.rk_killed = 77;
577 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
578 ATF_CHECK(r == -1 && errno == ESRCH);
579 ATF_CHECK_EQ(0, params.rk_killed);
582 ATF_TC_WITHOUT_HEAD(reaper_kill_normal);
583 ATF_TC_BODY(reaper_kill_normal, tc)
585 struct procctl_reaper_kill params;
587 pid_t parent, child, grandchild, pid;
592 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
593 ATF_REQUIRE_EQ(0, r);
596 ATF_REQUIRE_EQ(0, r);
598 ATF_REQUIRE(child != -1);
600 if (close(pip[0]) != 0)
603 if (grandchild == -1)
605 if (grandchild == 0) {
606 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
615 ATF_REQUIRE_EQ(0, r);
617 sr = read(pip[0], &(uint8_t){ 0 }, 1);
618 ATF_REQUIRE_EQ(1, sr);
620 params.rk_sig = SIGTERM;
622 params.rk_killed = 77;
623 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
625 ATF_CHECK_EQ(2, params.rk_killed);
627 pid = waitpid(child, &status, 0);
628 ATF_REQUIRE_EQ(child, pid);
629 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
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);
638 ATF_REQUIRE_EQ(0, r);
641 ATF_TC_WITHOUT_HEAD(reaper_kill_subtree);
642 ATF_TC_BODY(reaper_kill_subtree, tc)
644 struct procctl_reaper_kill params;
646 pid_t parent, child1, child2, grandchild1, grandchild2, pid;
651 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
652 ATF_REQUIRE_EQ(0, r);
655 ATF_REQUIRE_EQ(0, r);
657 ATF_REQUIRE(child1 != -1);
659 if (close(pip[0]) != 0)
661 grandchild1 = fork();
662 if (grandchild1 == -1)
664 if (grandchild1 == 0) {
665 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
674 ATF_REQUIRE(child2 != -1);
676 if (close(pip[0]) != 0)
678 grandchild2 = fork();
679 if (grandchild2 == -1)
681 if (grandchild2 == 0) {
682 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
691 ATF_REQUIRE_EQ(0, r);
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);
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, ¶ms);
703 ATF_REQUIRE_EQ(0, r);
704 ATF_REQUIRE_EQ(2, params.rk_killed);
705 ATF_CHECK_EQ(-1, params.rk_fpid);
707 pid = waitpid(child1, &status, 0);
708 ATF_REQUIRE_EQ(child1, pid);
709 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR1);
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);
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, ¶ms);
723 ATF_REQUIRE_EQ(0, r);
724 ATF_REQUIRE_EQ(2, params.rk_killed);
725 ATF_CHECK_EQ(-1, params.rk_fpid);
727 pid = waitpid(child2, &status, 0);
728 ATF_REQUIRE_EQ(child2, pid);
729 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR2);
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);
739 ATF_REQUIRE_EQ(0, r);
742 ATF_TC_WITHOUT_HEAD(reaper_pdfork);
743 ATF_TC_BODY(reaper_pdfork, tc)
745 struct procctl_reaper_status st;
746 pid_t child, grandchild, parent, pid;
750 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
751 ATF_REQUIRE_EQ(r, 0);
753 child = pdfork(&pd, 0);
754 ATF_REQUIRE(child != -1);
756 grandchild = pdfork(&pd, 0);
757 if (grandchild == -1)
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);
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);
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());