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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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, ¶ms); 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 } 795