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