1 /* $NetBSD: t_wait.c,v 1.10 2021/07/17 14:03:35 martin 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.10 2021/07/17 14:03:35 martin 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 48 ATF_TC(wait6_invalid); 49 ATF_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 55 ATF_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 64 ATF_TC(wait6_exited); 65 ATF_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 71 ATF_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 0: 80 exit(0x5a5a5a5a); 81 /*NOTREACHED*/ 82 case -1: 83 ATF_REQUIRE(pid > 0); 84 __unreachable(); 85 default: 86 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 87 ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 88 ATF_REQUIRE(si.si_status == 0x5a5a5a5a); 89 ATF_REQUIRE(si.si_pid == pid); 90 ATF_REQUIRE(si.si_uid == getuid()); 91 ATF_REQUIRE(si.si_code == CLD_EXITED); 92 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 93 (uintmax_t)si.si_utime); 94 break; 95 } 96 } 97 98 ATF_TC(wait6_terminated); 99 ATF_TC_HEAD(wait6_terminated, tc) 100 { 101 atf_tc_set_md_var(tc, "descr", 102 "Test that wait6(2) handled terminated process and code"); 103 } 104 105 ATF_TC_BODY(wait6_terminated, tc) 106 { 107 siginfo_t si; 108 struct wrusage wru; 109 int st; 110 pid_t pid; 111 112 switch (pid = fork()) { 113 case 0: 114 sleep(100); 115 /*FALLTHROUGH*/ 116 case -1: 117 ATF_REQUIRE(pid > 0); 118 __unreachable(); 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 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 128 (uintmax_t)si.si_utime); 129 break; 130 } 131 } 132 133 ATF_TC(wait6_coredumped); 134 ATF_TC_HEAD(wait6_coredumped, tc) 135 { 136 atf_tc_set_md_var(tc, "descr", 137 "Test that wait6(2) handled coredumped process and code"); 138 } 139 140 ATF_TC_BODY(wait6_coredumped, tc) 141 { 142 siginfo_t si; 143 struct wrusage wru; 144 int st; 145 pid_t pid; 146 static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 147 148 switch (pid = fork()) { 149 case 0: 150 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 151 *(char *)8 = 0; 152 /*FALLTHROUGH*/ 153 case -1: 154 ATF_REQUIRE(pid > 0); 155 __unreachable(); 156 default: 157 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 158 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 159 && WCOREDUMP(st)); 160 ATF_REQUIRE(si.si_status == SIGSEGV); 161 ATF_REQUIRE(si.si_pid == pid); 162 ATF_REQUIRE(si.si_uid == getuid()); 163 ATF_REQUIRE(si.si_code == CLD_DUMPED); 164 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 165 (uintmax_t)si.si_utime); 166 break; 167 } 168 } 169 170 ATF_TC(wait6_stop_and_go); 171 ATF_TC_HEAD(wait6_stop_and_go, tc) 172 { 173 atf_tc_set_md_var(tc, "descr", 174 "Test that wait6(2) handled stopped/continued process and code"); 175 } 176 177 ATF_TC_BODY(wait6_stop_and_go, tc) 178 { 179 siginfo_t si; 180 struct wrusage wru; 181 int st; 182 pid_t pid; 183 static const struct rlimit rl = { 0, 0 }; 184 185 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 186 switch (pid = fork()) { 187 case 0: 188 sleep(100); 189 /*FALLTHROUGH*/ 190 case -1: 191 ATF_REQUIRE(pid > 0); 192 __unreachable(); 193 default: 194 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 195 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 196 ATF_REQUIRE(!WIFEXITED(st)); 197 ATF_REQUIRE(!WIFSIGNALED(st)); 198 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 199 ATF_REQUIRE(!WIFCONTINUED(st)); 200 ATF_REQUIRE(si.si_status == SIGSTOP); 201 ATF_REQUIRE(si.si_pid == pid); 202 ATF_REQUIRE(si.si_uid == getuid()); 203 ATF_REQUIRE(si.si_code == CLD_STOPPED); 204 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 205 (uintmax_t)si.si_utime); 206 207 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 208 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 209 ATF_REQUIRE(!WIFEXITED(st)); 210 ATF_REQUIRE(!WIFSIGNALED(st)); 211 ATF_REQUIRE(WIFCONTINUED(st)); 212 ATF_REQUIRE(!WIFSTOPPED(st)); 213 ATF_REQUIRE(si.si_status == SIGCONT); 214 ATF_REQUIRE(si.si_pid == pid); 215 ATF_REQUIRE(si.si_uid == getuid()); 216 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 217 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 218 (uintmax_t)si.si_utime); 219 220 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 236 ATF_TC(wait6_stopgo_loop); 237 ATF_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 243 ATF_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 300 ATF_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