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