1314817Sngie/* $NetBSD: t_wait.c,v 1.8 2017/01/13 19:28:55 christos Exp $ */ 2303980Sngie 3303980Sngie/*- 4303980Sngie * Copyright (c) 2016 The NetBSD Foundation, Inc. 5303980Sngie * All rights reserved. 6303980Sngie * 7303980Sngie * This code is derived from software contributed to The NetBSD Foundation 8303980Sngie * by Christos Zoulas. 9303980Sngie * 10303980Sngie * Redistribution and use in source and binary forms, with or without 11303980Sngie * modification, are permitted provided that the following conditions 12303980Sngie * are met: 13303980Sngie * 1. Redistributions of source code must retain the above copyright 14303980Sngie * notice, this list of conditions and the following disclaimer. 15303980Sngie * 2. Redistributions in binary form must reproduce the above copyright 16303980Sngie * notice, this list of conditions and the following disclaimer in the 17303980Sngie * documentation and/or other materials provided with the distribution. 18303980Sngie * 19303980Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20303980Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21303980Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22303980Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23303980Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24303980Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25303980Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26303980Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27303980Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28303980Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29303980Sngie * POSSIBILITY OF SUCH DAMAGE. 30303980Sngie */ 31303980Sngie#include <sys/cdefs.h> 32314817Sngie__RCSID("$NetBSD: t_wait.c,v 1.8 2017/01/13 19:28:55 christos Exp $"); 33303980Sngie 34303980Sngie#include <sys/wait.h> 35303980Sngie#include <sys/resource.h> 36303980Sngie 37303980Sngie#include <errno.h> 38314817Sngie#include <inttypes.h> 39303980Sngie#include <limits.h> 40303980Sngie#include <pwd.h> 41303980Sngie#include <signal.h> 42314817Sngie#include <stdio.h> 43303980Sngie#include <stdlib.h> 44303980Sngie#include <unistd.h> 45303980Sngie 46303980Sngie#include <atf-c.h> 47303980Sngie 48303980SngieATF_TC(wait6_invalid); 49303980SngieATF_TC_HEAD(wait6_invalid, tc) 50303980Sngie{ 51303980Sngie atf_tc_set_md_var(tc, "descr", 52303980Sngie "Test that wait6(2) returns EINVAL with 0 options"); 53303980Sngie} 54303980Sngie 55303980SngieATF_TC_BODY(wait6_invalid, tc) 56303980Sngie{ 57303980Sngie siginfo_t si; 58303980Sngie struct wrusage wru; 59303980Sngie int st; 60303980Sngie ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1 61303980Sngie && errno == EINVAL); 62303980Sngie} 63303980Sngie 64303980SngieATF_TC(wait6_exited); 65303980SngieATF_TC_HEAD(wait6_exited, tc) 66303980Sngie{ 67303980Sngie atf_tc_set_md_var(tc, "descr", 68303980Sngie "Test that wait6(2) handled exiting process and code"); 69303980Sngie} 70303980Sngie 71303980SngieATF_TC_BODY(wait6_exited, tc) 72303980Sngie{ 73303980Sngie siginfo_t si; 74303980Sngie struct wrusage wru; 75303980Sngie int st; 76303980Sngie pid_t pid; 77303980Sngie 78303980Sngie switch (pid = fork()) { 79303980Sngie case -1: 80313535Sngie ATF_REQUIRE(pid > 0); 81303980Sngie case 0: 82303980Sngie exit(0x5a5a5a5a); 83303980Sngie /*NOTREACHED*/ 84303980Sngie default: 85313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 86303980Sngie ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 87303980Sngie ATF_REQUIRE(si.si_status = 0x5a5a5a5a); 88303980Sngie ATF_REQUIRE(si.si_pid == pid); 89303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 90303980Sngie ATF_REQUIRE(si.si_code == CLD_EXITED); 91304003Sngie#ifdef __NetBSD__ 92303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 93303980Sngie (uintmax_t)si.si_utime); 94304003Sngie#endif 95303980Sngie break; 96303980Sngie } 97303980Sngie} 98303980Sngie 99303980SngieATF_TC(wait6_terminated); 100303980SngieATF_TC_HEAD(wait6_terminated, tc) 101303980Sngie{ 102303980Sngie atf_tc_set_md_var(tc, "descr", 103303980Sngie "Test that wait6(2) handled terminated process and code"); 104303980Sngie} 105303980Sngie 106303980SngieATF_TC_BODY(wait6_terminated, tc) 107303980Sngie{ 108303980Sngie siginfo_t si; 109303980Sngie struct wrusage wru; 110303980Sngie int st; 111303980Sngie pid_t pid; 112303980Sngie 113303980Sngie switch (pid = fork()) { 114303980Sngie case 0: 115303980Sngie sleep(100); 116303980Sngie /*FALLTHROUGH*/ 117303980Sngie case -1: 118313535Sngie ATF_REQUIRE(pid > 0); 119303980Sngie default: 120303980Sngie ATF_REQUIRE(kill(pid, SIGTERM) == 0); 121313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 122303980Sngie ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); 123303980Sngie ATF_REQUIRE(si.si_status == SIGTERM); 124303980Sngie ATF_REQUIRE(si.si_pid == pid); 125303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 126303980Sngie ATF_REQUIRE(si.si_code == CLD_KILLED); 127304003Sngie#ifdef __NetBSD__ 128303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 129303980Sngie (uintmax_t)si.si_utime); 130304003Sngie#endif 131303980Sngie break; 132303980Sngie } 133303980Sngie} 134303980Sngie 135303980SngieATF_TC(wait6_coredumped); 136303980SngieATF_TC_HEAD(wait6_coredumped, tc) 137303980Sngie{ 138303980Sngie atf_tc_set_md_var(tc, "descr", 139303980Sngie "Test that wait6(2) handled coredumped process and code"); 140303980Sngie} 141303980Sngie 142303980SngieATF_TC_BODY(wait6_coredumped, tc) 143303980Sngie{ 144303980Sngie siginfo_t si; 145303980Sngie struct wrusage wru; 146303980Sngie int st; 147303980Sngie pid_t pid; 148303980Sngie static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 149303980Sngie 150303980Sngie switch (pid = fork()) { 151303980Sngie case 0: 152303980Sngie ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 153303980Sngie *(char *)8 = 0; 154303980Sngie /*FALLTHROUGH*/ 155303980Sngie case -1: 156313535Sngie ATF_REQUIRE(pid > 0); 157303980Sngie default: 158313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 159303980Sngie ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 160303980Sngie && WCOREDUMP(st)); 161303980Sngie ATF_REQUIRE(si.si_status == SIGSEGV); 162303980Sngie ATF_REQUIRE(si.si_pid == pid); 163303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 164303980Sngie ATF_REQUIRE(si.si_code == CLD_DUMPED); 165304003Sngie#ifdef __NetBSD__ 166303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 167303980Sngie (uintmax_t)si.si_utime); 168304003Sngie#endif 169303980Sngie break; 170303980Sngie } 171303980Sngie} 172303980Sngie 173303980SngieATF_TC(wait6_stop_and_go); 174303980SngieATF_TC_HEAD(wait6_stop_and_go, tc) 175303980Sngie{ 176303980Sngie atf_tc_set_md_var(tc, "descr", 177303980Sngie "Test that wait6(2) handled stopped/continued process and code"); 178303980Sngie} 179303980Sngie 180303980SngieATF_TC_BODY(wait6_stop_and_go, tc) 181303980Sngie{ 182303980Sngie siginfo_t si; 183303980Sngie struct wrusage wru; 184303980Sngie int st; 185303980Sngie pid_t pid; 186303980Sngie static const struct rlimit rl = { 0, 0 }; 187303980Sngie 188303980Sngie ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 189303980Sngie switch (pid = fork()) { 190303980Sngie case 0: 191303980Sngie sleep(100); 192303980Sngie /*FALLTHROUGH*/ 193303980Sngie case -1: 194313535Sngie ATF_REQUIRE(pid > 0); 195303980Sngie default: 196303980Sngie ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 197313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 198313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 199313535Sngie ATF_REQUIRE(!WIFSIGNALED(st)); 200303980Sngie ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 201313535Sngie ATF_REQUIRE(!WIFCONTINUED(st)); 202303980Sngie ATF_REQUIRE(si.si_status == SIGSTOP); 203303980Sngie ATF_REQUIRE(si.si_pid == pid); 204303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 205303980Sngie ATF_REQUIRE(si.si_code == CLD_STOPPED); 206304003Sngie#ifdef __NetBSD__ 207303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 208303980Sngie (uintmax_t)si.si_utime); 209304003Sngie#endif 210303980Sngie 211303980Sngie ATF_REQUIRE(kill(pid, SIGCONT) == 0); 212313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 213313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 214313535Sngie ATF_REQUIRE(!WIFSIGNALED(st)); 215303980Sngie ATF_REQUIRE(WIFCONTINUED(st)); 216313535Sngie ATF_REQUIRE(!WIFSTOPPED(st)); 217303980Sngie ATF_REQUIRE(si.si_status == SIGCONT); 218303980Sngie ATF_REQUIRE(si.si_pid == pid); 219303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 220303980Sngie ATF_REQUIRE(si.si_code == CLD_CONTINUED); 221304003Sngie#ifdef __NetBSD__ 222303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 223303980Sngie (uintmax_t)si.si_utime); 224304003Sngie#endif 225303980Sngie 226303980Sngie ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 227313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 228313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 229303980Sngie ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 230313535Sngie ATF_REQUIRE(!WIFSTOPPED(st)); 231313535Sngie ATF_REQUIRE(!WIFCONTINUED(st)); 232303980Sngie ATF_REQUIRE(si.si_status == SIGQUIT); 233303980Sngie ATF_REQUIRE(si.si_pid == pid); 234303980Sngie ATF_REQUIRE(si.si_uid == getuid()); 235303980Sngie ATF_REQUIRE(si.si_code == CLD_KILLED); 236304003Sngie#ifdef __NetBSD__ 237303980Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 238303980Sngie (uintmax_t)si.si_utime); 239304003Sngie#endif 240303980Sngie break; 241303980Sngie } 242303980Sngie} 243303980Sngie 244313535SngieATF_TC(wait6_stopgo_loop); 245313535SngieATF_TC_HEAD(wait6_stopgo_loop, tc) 246313535Sngie{ 247313535Sngie atf_tc_set_md_var(tc, "descr", 248313535Sngie "Test that wait6(2) handled stopped/continued process loop"); 249313535Sngie} 250313535Sngie 251313535SngieATF_TC_BODY(wait6_stopgo_loop, tc) 252313535Sngie{ 253313535Sngie siginfo_t si; 254313535Sngie struct wrusage wru; 255313535Sngie int st; 256313535Sngie pid_t pid; 257313535Sngie static const struct rlimit rl = { 0, 0 }; 258313535Sngie size_t N = 100; 259313535Sngie 260313535Sngie ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 261313535Sngie switch (pid = fork()) { 262313535Sngie case 0: 263313535Sngie sleep(100); 264313535Sngie /*FALLTHROUGH*/ 265313535Sngie case -1: 266313535Sngie ATF_REQUIRE(pid > 0); 267313535Sngie } 268313535Sngie 269313535Sngie printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N); 270313535Sngie while (N --> 0) { 271313535Sngie ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 272313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 273313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 274313535Sngie ATF_REQUIRE(!WIFSIGNALED(st)); 275313535Sngie ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 276313535Sngie ATF_REQUIRE(!WIFCONTINUED(st)); 277313535Sngie ATF_REQUIRE(si.si_status == SIGSTOP); 278313535Sngie ATF_REQUIRE(si.si_pid == pid); 279313535Sngie ATF_REQUIRE(si.si_uid == getuid()); 280313535Sngie ATF_REQUIRE(si.si_code == CLD_STOPPED); 281313535Sngie 282313535Sngie ATF_REQUIRE(kill(pid, SIGCONT) == 0); 283313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 284313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 285313535Sngie ATF_REQUIRE(!WIFSIGNALED(st)); 286313535Sngie ATF_REQUIRE(WIFCONTINUED(st)); 287313535Sngie ATF_REQUIRE(!WIFSTOPPED(st)); 288313535Sngie ATF_REQUIRE(si.si_status == SIGCONT); 289313535Sngie ATF_REQUIRE(si.si_pid == pid); 290313535Sngie ATF_REQUIRE(si.si_uid == getuid()); 291313535Sngie ATF_REQUIRE(si.si_code == CLD_CONTINUED); 292313535Sngie } 293313535Sngie ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 294313535Sngie ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 295313535Sngie ATF_REQUIRE(!WIFEXITED(st)); 296313535Sngie ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 297313535Sngie ATF_REQUIRE(!WIFSTOPPED(st)); 298313535Sngie ATF_REQUIRE(!WIFCONTINUED(st)); 299313535Sngie ATF_REQUIRE(si.si_status == SIGQUIT); 300313535Sngie ATF_REQUIRE(si.si_pid == pid); 301313535Sngie ATF_REQUIRE(si.si_uid == getuid()); 302313535Sngie ATF_REQUIRE(si.si_code == CLD_KILLED); 303313535Sngie#ifdef __NetBSD__ 304313535Sngie printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 305313535Sngie (uintmax_t)si.si_utime); 306313535Sngie#endif 307313535Sngie} 308313535Sngie 309303980SngieATF_TP_ADD_TCS(tp) 310303980Sngie{ 311303980Sngie 312303980Sngie ATF_TP_ADD_TC(tp, wait6_invalid); 313303980Sngie ATF_TP_ADD_TC(tp, wait6_exited); 314303980Sngie ATF_TP_ADD_TC(tp, wait6_terminated); 315303980Sngie ATF_TP_ADD_TC(tp, wait6_coredumped); 316303980Sngie ATF_TP_ADD_TC(tp, wait6_stop_and_go); 317313535Sngie ATF_TP_ADD_TC(tp, wait6_stopgo_loop); 318303980Sngie 319303980Sngie return atf_no_error(); 320303980Sngie} 321