1110385Sbenno/* $NetBSD: t_wait.c,v 1.10 2021/07/17 14:03:35 martin Exp $ */ 2110385Sbenno 3110385Sbenno/*- 4110385Sbenno * Copyright (c) 2016 The NetBSD Foundation, Inc. 5110385Sbenno * All rights reserved. 6110385Sbenno * 7110385Sbenno * This code is derived from software contributed to The NetBSD Foundation 8110385Sbenno * by Christos Zoulas. 9110385Sbenno * 10110385Sbenno * Redistribution and use in source and binary forms, with or without 11110385Sbenno * modification, are permitted provided that the following conditions 12110385Sbenno * are met: 13110385Sbenno * 1. Redistributions of source code must retain the above copyright 14110385Sbenno * notice, this list of conditions and the following disclaimer. 15110385Sbenno * 2. Redistributions in binary form must reproduce the above copyright 16110385Sbenno * notice, this list of conditions and the following disclaimer in the 17110385Sbenno * documentation and/or other materials provided with the distribution. 18110385Sbenno * 19110385Sbenno * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20110385Sbenno * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21110385Sbenno * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22110385Sbenno * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23110385Sbenno * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24110385Sbenno * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25110385Sbenno * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26110385Sbenno * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27110385Sbenno * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28110385Sbenno * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29110385Sbenno * POSSIBILITY OF SUCH DAMAGE. 30110385Sbenno */ 31110385Sbenno#include <sys/cdefs.h> 32110385Sbenno__RCSID("$NetBSD: t_wait.c,v 1.10 2021/07/17 14:03:35 martin Exp $"); 33110385Sbenno 34110385Sbenno#include <sys/wait.h> 35191375Sraj#include <sys/resource.h> 36110385Sbenno 37110385Sbenno#include <errno.h> 38110385Sbenno#include <inttypes.h> 39110385Sbenno#include <limits.h> 40110385Sbenno#include <pwd.h> 41110385Sbenno#include <signal.h> 42110385Sbenno#include <stdio.h> 43110385Sbenno#include <stdlib.h> 44198445Snwhitehorn#include <unistd.h> 45141224Sgrehan 46110385Sbenno#include <atf-c.h> 47110385Sbenno 48110385SbennoATF_TC(wait6_invalid); 49110385SbennoATF_TC_HEAD(wait6_invalid, tc) 50110385Sbenno{ 51190681Snwhitehorn atf_tc_set_md_var(tc, "descr", 52141224Sgrehan "Test that wait6(2) returns EINVAL with 0 options"); 53110385Sbenno} 54141224Sgrehan 55110385SbennoATF_TC_BODY(wait6_invalid, tc) 56110385Sbenno{ 57110385Sbenno siginfo_t si; 58110385Sbenno struct wrusage wru; 59110385Sbenno int st; 60110385Sbenno ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1 61110385Sbenno && errno == EINVAL); 62110385Sbenno} 63125614Sgrehan 64110385SbennoATF_TC(wait6_exited); 65141224SgrehanATF_TC_HEAD(wait6_exited, tc) 66110385Sbenno{ 67110385Sbenno atf_tc_set_md_var(tc, "descr", 68110385Sbenno "Test that wait6(2) handled exiting process and code"); 69176534Sraj} 70110385Sbenno 71176534SrajATF_TC_BODY(wait6_exited, tc) 72110385Sbenno{ 73110385Sbenno siginfo_t si; 74110385Sbenno struct wrusage wru; 75176742Sraj int st; 76176742Sraj pid_t pid; 77191375Sraj 78191375Sraj switch (pid = fork()) { 79191375Sraj case 0: 80176742Sraj exit(0x5a5a5a5a); 81236025Sraj /*NOTREACHED*/ 82236025Sraj case -1: 83110385Sbenno ATF_REQUIRE(pid > 0); 84110385Sbenno __unreachable(); 85110385Sbenno default: 86110385Sbenno ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 87110385Sbenno ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 88110385Sbenno ATF_REQUIRE(si.si_status == 0x5a5a5a5a); 89110385Sbenno ATF_REQUIRE(si.si_pid == pid); 90110385Sbenno ATF_REQUIRE(si.si_uid == getuid()); 91110385Sbenno ATF_REQUIRE(si.si_code == CLD_EXITED); 92110385Sbenno printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 93125614Sgrehan (uintmax_t)si.si_utime); 94125614Sgrehan break; 95110385Sbenno } 96110385Sbenno} 97176534Sraj 98176534SrajATF_TC(wait6_terminated); 99176534SrajATF_TC_HEAD(wait6_terminated, tc) 100176534Sraj{ 101176534Sraj atf_tc_set_md_var(tc, "descr", 102176534Sraj "Test that wait6(2) handled terminated process and code"); 103176534Sraj} 104198445Snwhitehorn 105198445SnwhitehornATF_TC_BODY(wait6_terminated, tc) 106198445Snwhitehorn{ 107198445Snwhitehorn siginfo_t si; 108198445Snwhitehorn struct wrusage wru; 109198445Snwhitehorn int st; 110236025Sraj pid_t pid; 111236025Sraj 112236025Sraj switch (pid = fork()) { 113236025Sraj case 0: 114236025Sraj sleep(100); 115236025Sraj /*FALLTHROUGH*/ 116236025Sraj case -1: 117236025Sraj ATF_REQUIRE(pid > 0); 118236025Sraj __unreachable(); 119236025Sraj default: 120236025Sraj ATF_REQUIRE(kill(pid, SIGTERM) == 0); 121236025Sraj ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 122236025Sraj ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); 123236025Sraj ATF_REQUIRE(si.si_status == SIGTERM); 124110385Sbenno ATF_REQUIRE(si.si_pid == pid); 125110385Sbenno ATF_REQUIRE(si.si_uid == getuid()); 126110385Sbenno ATF_REQUIRE(si.si_code == CLD_KILLED); 127176742Sraj printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 128176742Sraj (uintmax_t)si.si_utime); 129176742Sraj break; 130176742Sraj } 131176742Sraj} 132176742Sraj 133176742SrajATF_TC(wait6_coredumped); 134176742SrajATF_TC_HEAD(wait6_coredumped, tc) 135176742Sraj{ 136176742Sraj atf_tc_set_md_var(tc, "descr", 137176742Sraj "Test that wait6(2) handled coredumped process and code"); 138176742Sraj} 139176742Sraj 140176742SrajATF_TC_BODY(wait6_coredumped, tc) 141176742Sraj{ 142176742Sraj siginfo_t si; 143176742Sraj struct wrusage wru; 144176742Sraj int st; 145176742Sraj pid_t pid; 146176742Sraj static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 147176742Sraj 148176742Sraj switch (pid = fork()) { 149176742Sraj case 0: 150176742Sraj ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 151176742Sraj *(char *)8 = 0; 152176742Sraj /*FALLTHROUGH*/ 153176742Sraj case -1: 154176742Sraj ATF_REQUIRE(pid > 0); 155176742Sraj __unreachable(); 156176742Sraj default: 157176742Sraj ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 158176742Sraj ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 159176742Sraj && WCOREDUMP(st)); 160110385Sbenno ATF_REQUIRE(si.si_status == SIGSEGV); 161236025Sraj ATF_REQUIRE(si.si_pid == pid); 162236025Sraj ATF_REQUIRE(si.si_uid == getuid()); 163236025Sraj ATF_REQUIRE(si.si_code == CLD_DUMPED); 164236025Sraj printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 165236025Sraj (uintmax_t)si.si_utime); 166236025Sraj break; 167236025Sraj } 168236025Sraj} 169236025Sraj 170236025SrajATF_TC(wait6_stop_and_go); 171236025SrajATF_TC_HEAD(wait6_stop_and_go, tc) 172236025Sraj{ 173236025Sraj atf_tc_set_md_var(tc, "descr", 174236025Sraj "Test that wait6(2) handled stopped/continued process and code"); 175236025Sraj} 176236025Sraj 177236025SrajATF_TC_BODY(wait6_stop_and_go, tc) 178236025Sraj{ 179236025Sraj siginfo_t si; 180236025Sraj struct wrusage wru; 181236025Sraj int st; 182236025Sraj pid_t pid; 183236025Sraj static const struct rlimit rl = { 0, 0 }; 184236025Sraj 185236025Sraj ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 186236025Sraj switch (pid = fork()) { 187236025Sraj case 0: 188236025Sraj sleep(100); 189236025Sraj /*FALLTHROUGH*/ 190236025Sraj case -1: 191236025Sraj ATF_REQUIRE(pid > 0); 192236025Sraj __unreachable(); 193236025Sraj default: 194236025Sraj ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 195110385Sbenno ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 196110385Sbenno ATF_REQUIRE(!WIFEXITED(st)); 197110385Sbenno ATF_REQUIRE(!WIFSIGNALED(st)); 198110385Sbenno ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 199110385Sbenno ATF_REQUIRE(!WIFCONTINUED(st)); 200125614Sgrehan ATF_REQUIRE(si.si_status == SIGSTOP); 201110385Sbenno ATF_REQUIRE(si.si_pid == pid); 202110385Sbenno ATF_REQUIRE(si.si_uid == getuid()); 203125614Sgrehan ATF_REQUIRE(si.si_code == CLD_STOPPED); 204125614Sgrehan printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 205110385Sbenno (uintmax_t)si.si_utime); 206110385Sbenno 207191375Sraj ATF_REQUIRE(kill(pid, SIGCONT) == 0); 208191375Sraj ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 209191375Sraj ATF_REQUIRE(!WIFEXITED(st)); 210191375Sraj ATF_REQUIRE(!WIFSIGNALED(st)); 211191375Sraj ATF_REQUIRE(WIFCONTINUED(st)); 212191375Sraj ATF_REQUIRE(!WIFSTOPPED(st)); 213236025Sraj ATF_REQUIRE(si.si_status == SIGCONT); 214236025Sraj ATF_REQUIRE(si.si_pid == pid); 215236025Sraj ATF_REQUIRE(si.si_uid == getuid()); 216191375Sraj ATF_REQUIRE(si.si_code == CLD_CONTINUED); 217209975Snwhitehorn printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 218209975Snwhitehorn (uintmax_t)si.si_utime); 219190953Snwhitehorn 220110385Sbenno ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 221 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 222 ATF_REQUIRE(!WIFEXITED(st)); 223 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 224 ATF_REQUIRE(!WIFSTOPPED(st)); 225 ATF_REQUIRE(!WIFCONTINUED(st)); 226 ATF_REQUIRE(si.si_status == SIGQUIT); 227 ATF_REQUIRE(si.si_pid == pid); 228 ATF_REQUIRE(si.si_uid == getuid()); 229 ATF_REQUIRE(si.si_code == CLD_KILLED); 230 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 231 (uintmax_t)si.si_utime); 232 break; 233 } 234} 235 236ATF_TC(wait6_stopgo_loop); 237ATF_TC_HEAD(wait6_stopgo_loop, tc) 238{ 239 atf_tc_set_md_var(tc, "descr", 240 "Test that wait6(2) handled stopped/continued process loop"); 241} 242 243ATF_TC_BODY(wait6_stopgo_loop, tc) 244{ 245 siginfo_t si; 246 struct wrusage wru; 247 int st; 248 pid_t pid; 249 static const struct rlimit rl = { 0, 0 }; 250 size_t N = 100; 251 252 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 253 switch (pid = fork()) { 254 case 0: 255 sleep(100); 256 /*FALLTHROUGH*/ 257 case -1: 258 ATF_REQUIRE(pid > 0); 259 __unreachable(); 260 } 261 262 printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N); 263 while (N --> 0) { 264 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 265 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 266 ATF_REQUIRE(!WIFEXITED(st)); 267 ATF_REQUIRE(!WIFSIGNALED(st)); 268 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 269 ATF_REQUIRE(!WIFCONTINUED(st)); 270 ATF_REQUIRE(si.si_status == SIGSTOP); 271 ATF_REQUIRE(si.si_pid == pid); 272 ATF_REQUIRE(si.si_uid == getuid()); 273 ATF_REQUIRE(si.si_code == CLD_STOPPED); 274 275 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 276 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 277 ATF_REQUIRE(!WIFEXITED(st)); 278 ATF_REQUIRE(!WIFSIGNALED(st)); 279 ATF_REQUIRE(WIFCONTINUED(st)); 280 ATF_REQUIRE(!WIFSTOPPED(st)); 281 ATF_REQUIRE(si.si_status == SIGCONT); 282 ATF_REQUIRE(si.si_pid == pid); 283 ATF_REQUIRE(si.si_uid == getuid()); 284 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 285 } 286 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 287 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 288 ATF_REQUIRE(!WIFEXITED(st)); 289 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 290 ATF_REQUIRE(!WIFSTOPPED(st)); 291 ATF_REQUIRE(!WIFCONTINUED(st)); 292 ATF_REQUIRE(si.si_status == SIGQUIT); 293 ATF_REQUIRE(si.si_pid == pid); 294 ATF_REQUIRE(si.si_uid == getuid()); 295 ATF_REQUIRE(si.si_code == CLD_KILLED); 296 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 297 (uintmax_t)si.si_utime); 298} 299 300ATF_TP_ADD_TCS(tp) 301{ 302 303 ATF_TP_ADD_TC(tp, wait6_invalid); 304 ATF_TP_ADD_TC(tp, wait6_exited); 305 ATF_TP_ADD_TC(tp, wait6_terminated); 306 ATF_TP_ADD_TC(tp, wait6_coredumped); 307 ATF_TP_ADD_TC(tp, wait6_stop_and_go); 308 ATF_TP_ADD_TC(tp, wait6_stopgo_loop); 309 310 return atf_no_error(); 311} 312