1/* $NetBSD: t_wait.c,v 1.8 2017/01/13 19:28:55 christos Exp $ */ 2 3/*- 4 * Copyright (c) 2016 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31#include <sys/cdefs.h> 32__RCSID("$NetBSD: t_wait.c,v 1.8 2017/01/13 19:28:55 christos Exp $"); 33 34#include <sys/wait.h> 35#include <sys/resource.h> 36 37#include <errno.h> 38#include <inttypes.h> 39#include <limits.h> 40#include <pwd.h> 41#include <signal.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <unistd.h> 45 46#include <atf-c.h> 47 48ATF_TC(wait6_invalid); 49ATF_TC_HEAD(wait6_invalid, tc) 50{ 51 atf_tc_set_md_var(tc, "descr", 52 "Test that wait6(2) returns EINVAL with 0 options"); 53} 54 55ATF_TC_BODY(wait6_invalid, tc) 56{ 57 siginfo_t si; 58 struct wrusage wru; 59 int st; 60 ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1 61 && errno == EINVAL); 62} 63 64ATF_TC(wait6_exited); 65ATF_TC_HEAD(wait6_exited, tc) 66{ 67 atf_tc_set_md_var(tc, "descr", 68 "Test that wait6(2) handled exiting process and code"); 69} 70 71ATF_TC_BODY(wait6_exited, tc) 72{ 73 siginfo_t si; 74 struct wrusage wru; 75 int st; 76 pid_t pid; 77 78 switch (pid = fork()) { 79 case -1: 80 ATF_REQUIRE(pid > 0); 81 case 0: 82 exit(0x5a5a5a5a); 83 /*NOTREACHED*/ 84 default: 85 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 86 ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 87 ATF_REQUIRE(si.si_status = 0x5a5a5a5a); 88 ATF_REQUIRE(si.si_pid == pid); 89 ATF_REQUIRE(si.si_uid == getuid()); 90 ATF_REQUIRE(si.si_code == CLD_EXITED); 91#ifdef __NetBSD__ 92 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 93 (uintmax_t)si.si_utime); 94#endif 95 break; 96 } 97} 98 99ATF_TC(wait6_terminated); 100ATF_TC_HEAD(wait6_terminated, tc) 101{ 102 atf_tc_set_md_var(tc, "descr", 103 "Test that wait6(2) handled terminated process and code"); 104} 105 106ATF_TC_BODY(wait6_terminated, tc) 107{ 108 siginfo_t si; 109 struct wrusage wru; 110 int st; 111 pid_t pid; 112 113 switch (pid = fork()) { 114 case 0: 115 sleep(100); 116 /*FALLTHROUGH*/ 117 case -1: 118 ATF_REQUIRE(pid > 0); 119 default: 120 ATF_REQUIRE(kill(pid, SIGTERM) == 0); 121 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 122 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); 123 ATF_REQUIRE(si.si_status == SIGTERM); 124 ATF_REQUIRE(si.si_pid == pid); 125 ATF_REQUIRE(si.si_uid == getuid()); 126 ATF_REQUIRE(si.si_code == CLD_KILLED); 127#ifdef __NetBSD__ 128 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 129 (uintmax_t)si.si_utime); 130#endif 131 break; 132 } 133} 134 135ATF_TC(wait6_coredumped); 136ATF_TC_HEAD(wait6_coredumped, tc) 137{ 138 atf_tc_set_md_var(tc, "descr", 139 "Test that wait6(2) handled coredumped process and code"); 140} 141 142ATF_TC_BODY(wait6_coredumped, tc) 143{ 144 siginfo_t si; 145 struct wrusage wru; 146 int st; 147 pid_t pid; 148 static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 149 150 switch (pid = fork()) { 151 case 0: 152 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 153 *(char *)8 = 0; 154 /*FALLTHROUGH*/ 155 case -1: 156 ATF_REQUIRE(pid > 0); 157 default: 158 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 159 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 160 && WCOREDUMP(st)); 161 ATF_REQUIRE(si.si_status == SIGSEGV); 162 ATF_REQUIRE(si.si_pid == pid); 163 ATF_REQUIRE(si.si_uid == getuid()); 164 ATF_REQUIRE(si.si_code == CLD_DUMPED); 165#ifdef __NetBSD__ 166 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 167 (uintmax_t)si.si_utime); 168#endif 169 break; 170 } 171} 172 173ATF_TC(wait6_stop_and_go); 174ATF_TC_HEAD(wait6_stop_and_go, tc) 175{ 176 atf_tc_set_md_var(tc, "descr", 177 "Test that wait6(2) handled stopped/continued process and code"); 178} 179 180ATF_TC_BODY(wait6_stop_and_go, tc) 181{ 182 siginfo_t si; 183 struct wrusage wru; 184 int st; 185 pid_t pid; 186 static const struct rlimit rl = { 0, 0 }; 187 188 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 189 switch (pid = fork()) { 190 case 0: 191 sleep(100); 192 /*FALLTHROUGH*/ 193 case -1: 194 ATF_REQUIRE(pid > 0); 195 default: 196 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 197 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 198 ATF_REQUIRE(!WIFEXITED(st)); 199 ATF_REQUIRE(!WIFSIGNALED(st)); 200 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 201 ATF_REQUIRE(!WIFCONTINUED(st)); 202 ATF_REQUIRE(si.si_status == SIGSTOP); 203 ATF_REQUIRE(si.si_pid == pid); 204 ATF_REQUIRE(si.si_uid == getuid()); 205 ATF_REQUIRE(si.si_code == CLD_STOPPED); 206#ifdef __NetBSD__ 207 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 208 (uintmax_t)si.si_utime); 209#endif 210 211 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 212 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 213 ATF_REQUIRE(!WIFEXITED(st)); 214 ATF_REQUIRE(!WIFSIGNALED(st)); 215 ATF_REQUIRE(WIFCONTINUED(st)); 216 ATF_REQUIRE(!WIFSTOPPED(st)); 217 ATF_REQUIRE(si.si_status == SIGCONT); 218 ATF_REQUIRE(si.si_pid == pid); 219 ATF_REQUIRE(si.si_uid == getuid()); 220 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 221#ifdef __NetBSD__ 222 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 223 (uintmax_t)si.si_utime); 224#endif 225 226 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 227 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 228 ATF_REQUIRE(!WIFEXITED(st)); 229 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 230 ATF_REQUIRE(!WIFSTOPPED(st)); 231 ATF_REQUIRE(!WIFCONTINUED(st)); 232 ATF_REQUIRE(si.si_status == SIGQUIT); 233 ATF_REQUIRE(si.si_pid == pid); 234 ATF_REQUIRE(si.si_uid == getuid()); 235 ATF_REQUIRE(si.si_code == CLD_KILLED); 236#ifdef __NetBSD__ 237 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 238 (uintmax_t)si.si_utime); 239#endif 240 break; 241 } 242} 243 244ATF_TC(wait6_stopgo_loop); 245ATF_TC_HEAD(wait6_stopgo_loop, tc) 246{ 247 atf_tc_set_md_var(tc, "descr", 248 "Test that wait6(2) handled stopped/continued process loop"); 249} 250 251ATF_TC_BODY(wait6_stopgo_loop, tc) 252{ 253 siginfo_t si; 254 struct wrusage wru; 255 int st; 256 pid_t pid; 257 static const struct rlimit rl = { 0, 0 }; 258 size_t N = 100; 259 260 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 261 switch (pid = fork()) { 262 case 0: 263 sleep(100); 264 /*FALLTHROUGH*/ 265 case -1: 266 ATF_REQUIRE(pid > 0); 267 } 268 269 printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N); 270 while (N --> 0) { 271 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 272 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 273 ATF_REQUIRE(!WIFEXITED(st)); 274 ATF_REQUIRE(!WIFSIGNALED(st)); 275 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 276 ATF_REQUIRE(!WIFCONTINUED(st)); 277 ATF_REQUIRE(si.si_status == SIGSTOP); 278 ATF_REQUIRE(si.si_pid == pid); 279 ATF_REQUIRE(si.si_uid == getuid()); 280 ATF_REQUIRE(si.si_code == CLD_STOPPED); 281 282 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 283 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 284 ATF_REQUIRE(!WIFEXITED(st)); 285 ATF_REQUIRE(!WIFSIGNALED(st)); 286 ATF_REQUIRE(WIFCONTINUED(st)); 287 ATF_REQUIRE(!WIFSTOPPED(st)); 288 ATF_REQUIRE(si.si_status == SIGCONT); 289 ATF_REQUIRE(si.si_pid == pid); 290 ATF_REQUIRE(si.si_uid == getuid()); 291 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 292 } 293 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 294 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 295 ATF_REQUIRE(!WIFEXITED(st)); 296 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 297 ATF_REQUIRE(!WIFSTOPPED(st)); 298 ATF_REQUIRE(!WIFCONTINUED(st)); 299 ATF_REQUIRE(si.si_status == SIGQUIT); 300 ATF_REQUIRE(si.si_pid == pid); 301 ATF_REQUIRE(si.si_uid == getuid()); 302 ATF_REQUIRE(si.si_code == CLD_KILLED); 303#ifdef __NetBSD__ 304 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 305 (uintmax_t)si.si_utime); 306#endif 307} 308 309ATF_TP_ADD_TCS(tp) 310{ 311 312 ATF_TP_ADD_TC(tp, wait6_invalid); 313 ATF_TP_ADD_TC(tp, wait6_exited); 314 ATF_TP_ADD_TC(tp, wait6_terminated); 315 ATF_TP_ADD_TC(tp, wait6_coredumped); 316 ATF_TP_ADD_TC(tp, wait6_stop_and_go); 317 ATF_TP_ADD_TC(tp, wait6_stopgo_loop); 318 319 return atf_no_error(); 320} 321