ATF_TC_BODY(wait6_stopgo_loop, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; static const struct rlimit rl = { 0, 0 }; size_t N = 100; ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); switch (pid = fork()) { case 0: sleep(100); /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); } printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N); while (N --> 0) { ATF_REQUIRE(kill(pid, SIGSTOP) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGSTOP); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_STOPPED); ATF_REQUIRE(kill(pid, SIGCONT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFCONTINUED(st)); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(si.si_status == SIGCONT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_CONTINUED); } ATF_REQUIRE(kill(pid, SIGQUIT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGQUIT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_KILLED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif }
ATF_TC_BODY(wait6_stop_and_go, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; static const struct rlimit rl = { 0, 0 }; ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); switch (pid = fork()) { case 0: sleep(100); /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); default: ATF_REQUIRE(kill(pid, SIGSTOP) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGSTOP); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_STOPPED); printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); ATF_REQUIRE(kill(pid, SIGCONT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(!WIFSIGNALED(st)); ATF_REQUIRE(WIFCONTINUED(st)); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(si.si_status == SIGCONT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_CONTINUED); printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); ATF_REQUIRE(kill(pid, SIGQUIT) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(!WIFEXITED(st)); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); ATF_REQUIRE(!WIFSTOPPED(st)); ATF_REQUIRE(!WIFCONTINUED(st)); ATF_REQUIRE(si.si_status == SIGQUIT); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_KILLED); printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); break; } }
ATF_TC_BODY(wait6_exited, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; switch (pid = fork()) { case -1: ATF_REQUIRE(pid > 0); case 0: exit(0x5a5a5a5a); /*NOTREACHED*/ default: ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); ATF_REQUIRE(si.si_status = 0x5a5a5a5a); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_EXITED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif break; } }
ATF_TC_BODY(wait6_coredumped, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; switch (pid = fork()) { case 0: ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); *(char *)8 = 0; /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); default: ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV && WCOREDUMP(st)); ATF_REQUIRE(si.si_status == SIGSEGV); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_DUMPED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif break; } }
ATF_TC_BODY(wait6_terminated, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; switch (pid = fork()) { case 0: sleep(100); /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); default: ATF_REQUIRE(kill(pid, SIGTERM) == 0); ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); ATF_REQUIRE(si.si_status == SIGTERM); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_KILLED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif break; } }
ATF_TC_BODY(wait6_noproc, tc) { siginfo_t si; struct wrusage wru; int st; ATF_REQUIRE(wait6(P_ALL, 0, &st, WEXITED, &wru, &si) == -1 && errno == ECHILD); }
ATF_TC_BODY(wait6_invalid, tc) { siginfo_t si; struct wrusage wru; int st; ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1 && errno == EINVAL); }
ATF_TC_BODY(wait6_options, tc) { size_t i = 0; int o; while((o = get_options6(i++)) != -1) { printf("Testing wait6(2) with options %x\n", o); ATF_REQUIRE_ERRNO(ECHILD, wait6(P_ALL, 0, NULL, o | TWAIT_OPTION, NULL, NULL) == -1); } }
int waitid(idtype_t idtype, id_t id, siginfo_t *info, int flags) { int status; switch (wait6(idtype, id, &status, flags, NULL, info)) { case -1: return -1; case 0: if (info != NULL) memset(info, 0, sizeof(*info)); /*FALLTHROUGH*/ default: return 0; } }
ATF_TC_BODY(wait6_coredumped, tc) { siginfo_t si; struct wrusage wru; int st; pid_t pid; static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; #ifdef __FreeBSD__ int coredump_enabled; size_t ce_len = sizeof(coredump_enabled); if (sysctlbyname("kern.coredump", &coredump_enabled, &ce_len, NULL, 0) == 0 && !coredump_enabled) atf_tc_skip("Coredumps disabled"); #endif switch (pid = fork()) { case 0: ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); *(char *)8 = 0; /*FALLTHROUGH*/ case -1: ATF_REQUIRE(pid > 0); default: ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV && WCOREDUMP(st)); ATF_REQUIRE(si.si_status == SIGSEGV); ATF_REQUIRE(si.si_pid == pid); ATF_REQUIRE(si.si_uid == getuid()); ATF_REQUIRE(si.si_code == CLD_DUMPED); #ifdef __NetBSD__ printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, (uintmax_t)si.si_utime); #endif break; } }
ATF_TC_BODY(wait6, tc) { ATF_REQUIRE_ERRNO(ECHILD, wait6(P_ALL, 0, NULL, WTRAPPED | WEXITED | TWAIT_OPTION, NULL, NULL) == -1); }