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 __FBSDID("$FreeBSD$");
30 #include <sys/procctl.h>
31 #include <sys/procdesc.h>
40 dummy_sighandler(int sig __unused, siginfo_t *info __unused, void *ctx __unused)
44 ATF_TC_WITHOUT_HEAD(reaper_wait_child_first);
45 ATF_TC_BODY(reaper_wait_child_first, tc)
47 pid_t parent, child, grandchild, pid;
52 pid = waitpid(-1, NULL, WNOHANG);
53 ATF_REQUIRE(pid == -1 && errno == ECHILD);
56 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
63 ATF_REQUIRE(child != -1);
65 if (close(pip[1]) != 0)
70 else if (grandchild == 0) {
71 if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
73 if (getppid() != parent)
80 pid = waitpid(child, &status, 0);
81 ATF_REQUIRE_EQ(child, pid);
82 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
88 pid = waitpid(-1, &status, 0);
89 ATF_REQUIRE(pid > 0 && pid != child);
90 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
97 ATF_TC_WITHOUT_HEAD(reaper_wait_grandchild_first);
98 ATF_TC_BODY(reaper_wait_grandchild_first, tc)
100 pid_t parent, child, grandchild, pid;
104 pid = waitpid(-1, NULL, WNOHANG);
105 ATF_REQUIRE(pid == -1 && errno == ECHILD);
108 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
109 ATF_REQUIRE_EQ(0, r);
112 ATF_REQUIRE(child != -1);
115 if (grandchild == -1)
117 else if (grandchild == 0)
120 if (waitid(P_PID, grandchild, NULL,
121 WNOWAIT | WEXITED) != 0)
127 pid = waitpid(child, &status, 0);
128 ATF_REQUIRE_EQ(child, pid);
129 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
132 pid = waitpid(-1, &status, 0);
133 ATF_REQUIRE(pid > 0 && pid != child);
134 r = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
138 ATF_TC(reaper_sigchld_child_first);
139 ATF_TC_HEAD(reaper_sigchld_child_first, tc)
141 atf_tc_set_md_var(tc, "timeout", "2");
143 ATF_TC_BODY(reaper_sigchld_child_first, tc)
145 struct sigaction act;
148 pid_t parent, child, grandchild, pid;
153 pid = waitpid(-1, NULL, WNOHANG);
154 ATF_REQUIRE(pid == -1 && errno == ECHILD);
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);
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);
171 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
172 ATF_REQUIRE_EQ(0, r);
175 ATF_REQUIRE_EQ(0, r);
178 ATF_REQUIRE(child != -1);
180 if (close(pip[1]) != 0)
183 if (grandchild == -1)
185 else if (grandchild == 0) {
186 if (read(pip[0], &(uint8_t){ 0 }, 1) != 0)
188 if (getppid() != parent)
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);
202 pid = waitpid(child, NULL, 0);
203 ATF_REQUIRE_EQ(child, pid);
206 ATF_REQUIRE_EQ(0, r);
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);
218 pid = waitpid(-1, NULL, 0);
219 ATF_REQUIRE_EQ(grandchild, pid);
222 ATF_REQUIRE_EQ(0, r);
225 ATF_TC(reaper_sigchld_grandchild_first);
226 ATF_TC_HEAD(reaper_sigchld_grandchild_first, tc)
228 atf_tc_set_md_var(tc, "timeout", "2");
230 ATF_TC_BODY(reaper_sigchld_grandchild_first, tc)
232 struct sigaction act;
235 pid_t parent, child, grandchild, pid;
239 pid = waitpid(-1, NULL, WNOHANG);
240 ATF_REQUIRE(pid == -1 && errno == ECHILD);
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);
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);
257 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
258 ATF_REQUIRE_EQ(0, r);
261 ATF_REQUIRE(child != -1);
264 if (grandchild == -1)
266 else if (grandchild == 0)
269 if (waitid(P_PID, grandchild, NULL,
270 WNOWAIT | WEXITED) != 0)
276 pid = waitpid(child, NULL, 0);
277 ATF_REQUIRE_EQ(child, pid);
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);
289 pid = waitpid(-1, NULL, 0);
290 ATF_REQUIRE_EQ(grandchild, pid);
293 ATF_TC_WITHOUT_HEAD(reaper_status);
294 ATF_TC_BODY(reaper_status, tc)
296 struct procctl_reaper_status st;
298 pid_t parent, child, pid;
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);
312 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
313 ATF_REQUIRE_EQ(0, r);
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);
325 ATF_REQUIRE_EQ(0, r);
327 ATF_REQUIRE(child != -1);
329 if (close(pip[0]) != 0)
331 if (procctl(P_PID, parent, PROC_REAP_STATUS, &st) != 0)
333 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
335 if (procctl(P_PID, getpid(), PROC_REAP_STATUS, &st) != 0)
337 if (write(pip[1], &st, sizeof(st)) != (ssize_t)sizeof(st))
342 ATF_REQUIRE_EQ(0, r);
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);
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);
362 ATF_REQUIRE_EQ(0, r);
363 pid = waitpid(child, &status, 0);
364 ATF_REQUIRE_EQ(child, pid);
365 ATF_CHECK_EQ(0, status);
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);
377 ATF_TC_WITHOUT_HEAD(reaper_getpids);
378 ATF_TC_BODY(reaper_getpids, tc)
380 struct procctl_reaper_pidinfo info[10];
382 pid_t parent, child, grandchild, pid;
383 int r, status, childidx;
384 int pipa[2], pipb[2];
387 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
388 ATF_REQUIRE_EQ(0, r);
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]),
397 ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
400 ATF_REQUIRE_EQ(0, r);
402 ATF_REQUIRE_EQ(0, r);
404 ATF_REQUIRE(child != -1);
406 if (close(pipa[1]) != 0)
408 if (close(pipb[0]) != 0)
410 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
413 if (grandchild == -1)
415 if (grandchild == 0) {
416 if (write(pipb[1], &(uint8_t){ 0 }, 1) != 1)
418 if (read(pipa[0], &(uint8_t){ 0 }, 1) != 1)
426 ATF_REQUIRE_EQ(0, r);
428 ATF_REQUIRE_EQ(0, r);
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]),
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);
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);
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]),
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);
472 r = kill(child, SIGTERM);
473 ATF_REQUIRE_EQ(0, r);
475 pid = waitpid(child, &status, 0);
476 ATF_REQUIRE_EQ(child, pid);
477 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
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]),
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);
494 sr = write(pipa[1], &(uint8_t){ 0 }, 1);
495 ATF_REQUIRE_EQ(1, sr);
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]),
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);
512 pid = waitpid(grandchild, &status, 0);
513 ATF_REQUIRE_EQ(grandchild, pid);
514 ATF_CHECK_EQ(0, status);
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]),
523 ATF_CHECK_EQ(0, info[0].pi_flags & REAPER_PIDINFO_VALID);
526 ATF_REQUIRE_EQ(0, r);
528 ATF_REQUIRE_EQ(0, r);
531 ATF_TC_WITHOUT_HEAD(reaper_kill_badsig);
532 ATF_TC_BODY(reaper_kill_badsig, tc)
534 struct procctl_reaper_kill params;
539 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
540 ATF_REQUIRE_EQ(0, r);
544 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
545 ATF_CHECK(r == -1 && errno == EINVAL);
548 ATF_TC_WITHOUT_HEAD(reaper_kill_sigzero);
549 ATF_TC_BODY(reaper_kill_sigzero, tc)
551 struct procctl_reaper_kill params;
556 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
557 ATF_REQUIRE_EQ(0, r);
561 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
562 ATF_CHECK(r == -1 && errno == EINVAL);
565 ATF_TC_WITHOUT_HEAD(reaper_kill_empty);
566 ATF_TC_BODY(reaper_kill_empty, tc)
568 struct procctl_reaper_kill params;
573 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
574 ATF_REQUIRE_EQ(0, r);
576 params.rk_sig = SIGTERM;
578 params.rk_killed = 77;
579 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
580 ATF_CHECK(r == -1 && errno == ESRCH);
581 ATF_CHECK_EQ(0, params.rk_killed);
584 ATF_TC_WITHOUT_HEAD(reaper_kill_normal);
585 ATF_TC_BODY(reaper_kill_normal, tc)
587 struct procctl_reaper_kill params;
589 pid_t parent, child, grandchild, pid;
594 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
595 ATF_REQUIRE_EQ(0, r);
598 ATF_REQUIRE_EQ(0, r);
600 ATF_REQUIRE(child != -1);
602 if (close(pip[0]) != 0)
605 if (grandchild == -1)
607 if (grandchild == 0) {
608 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
617 ATF_REQUIRE_EQ(0, r);
619 sr = read(pip[0], &(uint8_t){ 0 }, 1);
620 ATF_REQUIRE_EQ(1, sr);
622 params.rk_sig = SIGTERM;
624 params.rk_killed = 77;
625 r = procctl(P_PID, parent, PROC_REAP_KILL, ¶ms);
627 ATF_CHECK_EQ(2, params.rk_killed);
629 pid = waitpid(child, &status, 0);
630 ATF_REQUIRE_EQ(child, pid);
631 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM);
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);
640 ATF_REQUIRE_EQ(0, r);
643 ATF_TC_WITHOUT_HEAD(reaper_kill_subtree);
644 ATF_TC_BODY(reaper_kill_subtree, tc)
646 struct procctl_reaper_kill params;
648 pid_t parent, child1, child2, grandchild1, grandchild2, pid;
653 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
654 ATF_REQUIRE_EQ(0, r);
657 ATF_REQUIRE_EQ(0, r);
659 ATF_REQUIRE(child1 != -1);
661 if (close(pip[0]) != 0)
663 grandchild1 = fork();
664 if (grandchild1 == -1)
666 if (grandchild1 == 0) {
667 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
676 ATF_REQUIRE(child2 != -1);
678 if (close(pip[0]) != 0)
680 grandchild2 = fork();
681 if (grandchild2 == -1)
683 if (grandchild2 == 0) {
684 if (write(pip[1], &(uint8_t){ 0 }, 1) != 1)
693 ATF_REQUIRE_EQ(0, r);
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);
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, ¶ms);
705 ATF_REQUIRE_EQ(0, r);
706 ATF_REQUIRE_EQ(2, params.rk_killed);
707 ATF_CHECK_EQ(-1, params.rk_fpid);
709 pid = waitpid(child1, &status, 0);
710 ATF_REQUIRE_EQ(child1, pid);
711 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR1);
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);
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, ¶ms);
725 ATF_REQUIRE_EQ(0, r);
726 ATF_REQUIRE_EQ(2, params.rk_killed);
727 ATF_CHECK_EQ(-1, params.rk_fpid);
729 pid = waitpid(child2, &status, 0);
730 ATF_REQUIRE_EQ(child2, pid);
731 ATF_CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGUSR2);
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);
741 ATF_REQUIRE_EQ(0, r);
744 ATF_TC_WITHOUT_HEAD(reaper_pdfork);
745 ATF_TC_BODY(reaper_pdfork, tc)
747 struct procctl_reaper_status st;
748 pid_t child, grandchild, parent, pid;
752 r = procctl(P_PID, parent, PROC_REAP_ACQUIRE, NULL);
753 ATF_REQUIRE_EQ(r, 0);
755 child = pdfork(&pd, 0);
756 ATF_REQUIRE(child != -1);
758 grandchild = pdfork(&pd, 0);
759 if (grandchild == -1)
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);
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);
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());