1 /* $NetBSD: t_wait.c,v 1.7 2016/11/06 15:04:14 kamil 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.7 2016/11/06 15:04:14 kamil Exp $"); 33 34 #include <sys/wait.h> 35 #include <sys/resource.h> 36 37 #include <stdio.h> 38 #include <errno.h> 39 #include <limits.h> 40 #include <pwd.h> 41 #include <signal.h> 42 #include <stdlib.h> 43 #include <unistd.h> 44 45 #include <atf-c.h> 46 47 #ifdef __FreeBSD__ 48 #define wrusage __wrusage 49 #endif 50 51 ATF_TC(wait6_invalid); 52 ATF_TC_HEAD(wait6_invalid, tc) 53 { 54 atf_tc_set_md_var(tc, "descr", 55 "Test that wait6(2) returns EINVAL with 0 options"); 56 } 57 58 ATF_TC_BODY(wait6_invalid, tc) 59 { 60 siginfo_t si; 61 struct wrusage wru; 62 int st; 63 ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1 64 && errno == EINVAL); 65 } 66 67 ATF_TC(wait6_exited); 68 ATF_TC_HEAD(wait6_exited, tc) 69 { 70 atf_tc_set_md_var(tc, "descr", 71 "Test that wait6(2) handled exiting process and code"); 72 } 73 74 ATF_TC_BODY(wait6_exited, tc) 75 { 76 siginfo_t si; 77 struct wrusage wru; 78 int st; 79 pid_t pid; 80 81 switch (pid = fork()) { 82 case -1: 83 ATF_REQUIRE(pid > 0); 84 case 0: 85 exit(0x5a5a5a5a); 86 /*NOTREACHED*/ 87 default: 88 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 89 ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 90 ATF_REQUIRE(si.si_status = 0x5a5a5a5a); 91 ATF_REQUIRE(si.si_pid == pid); 92 ATF_REQUIRE(si.si_uid == getuid()); 93 ATF_REQUIRE(si.si_code == CLD_EXITED); 94 #ifdef __NetBSD__ 95 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 96 (uintmax_t)si.si_utime); 97 #endif 98 break; 99 } 100 } 101 102 ATF_TC(wait6_terminated); 103 ATF_TC_HEAD(wait6_terminated, tc) 104 { 105 atf_tc_set_md_var(tc, "descr", 106 "Test that wait6(2) handled terminated process and code"); 107 } 108 109 ATF_TC_BODY(wait6_terminated, tc) 110 { 111 siginfo_t si; 112 struct wrusage wru; 113 int st; 114 pid_t pid; 115 116 switch (pid = fork()) { 117 case 0: 118 sleep(100); 119 /*FALLTHROUGH*/ 120 case -1: 121 ATF_REQUIRE(pid > 0); 122 default: 123 ATF_REQUIRE(kill(pid, SIGTERM) == 0); 124 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 125 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); 126 ATF_REQUIRE(si.si_status == SIGTERM); 127 ATF_REQUIRE(si.si_pid == pid); 128 ATF_REQUIRE(si.si_uid == getuid()); 129 ATF_REQUIRE(si.si_code == CLD_KILLED); 130 #ifdef __NetBSD__ 131 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 132 (uintmax_t)si.si_utime); 133 #endif 134 break; 135 } 136 } 137 138 ATF_TC(wait6_coredumped); 139 ATF_TC_HEAD(wait6_coredumped, tc) 140 { 141 atf_tc_set_md_var(tc, "descr", 142 "Test that wait6(2) handled coredumped process and code"); 143 } 144 145 ATF_TC_BODY(wait6_coredumped, tc) 146 { 147 siginfo_t si; 148 struct wrusage wru; 149 int st; 150 pid_t pid; 151 static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 152 153 switch (pid = fork()) { 154 case 0: 155 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 156 *(char *)8 = 0; 157 /*FALLTHROUGH*/ 158 case -1: 159 ATF_REQUIRE(pid > 0); 160 default: 161 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 162 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 163 && WCOREDUMP(st)); 164 ATF_REQUIRE(si.si_status == SIGSEGV); 165 ATF_REQUIRE(si.si_pid == pid); 166 ATF_REQUIRE(si.si_uid == getuid()); 167 ATF_REQUIRE(si.si_code == CLD_DUMPED); 168 #ifdef __NetBSD__ 169 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 170 (uintmax_t)si.si_utime); 171 #endif 172 break; 173 } 174 } 175 176 ATF_TC(wait6_stop_and_go); 177 ATF_TC_HEAD(wait6_stop_and_go, tc) 178 { 179 atf_tc_set_md_var(tc, "descr", 180 "Test that wait6(2) handled stopped/continued process and code"); 181 } 182 183 ATF_TC_BODY(wait6_stop_and_go, tc) 184 { 185 siginfo_t si; 186 struct wrusage wru; 187 int st; 188 pid_t pid; 189 static const struct rlimit rl = { 0, 0 }; 190 191 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 192 switch (pid = fork()) { 193 case 0: 194 sleep(100); 195 /*FALLTHROUGH*/ 196 case -1: 197 ATF_REQUIRE(pid > 0); 198 default: 199 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 200 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 201 ATF_REQUIRE(!WIFEXITED(st)); 202 ATF_REQUIRE(!WIFSIGNALED(st)); 203 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 204 ATF_REQUIRE(!WIFCONTINUED(st)); 205 ATF_REQUIRE(si.si_status == SIGSTOP); 206 ATF_REQUIRE(si.si_pid == pid); 207 ATF_REQUIRE(si.si_uid == getuid()); 208 ATF_REQUIRE(si.si_code == CLD_STOPPED); 209 #ifdef __NetBSD__ 210 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 211 (uintmax_t)si.si_utime); 212 #endif 213 214 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 215 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 216 ATF_REQUIRE(!WIFEXITED(st)); 217 ATF_REQUIRE(!WIFSIGNALED(st)); 218 ATF_REQUIRE(WIFCONTINUED(st)); 219 ATF_REQUIRE(!WIFSTOPPED(st)); 220 ATF_REQUIRE(si.si_status == SIGCONT); 221 ATF_REQUIRE(si.si_pid == pid); 222 ATF_REQUIRE(si.si_uid == getuid()); 223 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 224 #ifdef __NetBSD__ 225 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 226 (uintmax_t)si.si_utime); 227 #endif 228 229 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 230 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 231 ATF_REQUIRE(!WIFEXITED(st)); 232 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 233 ATF_REQUIRE(!WIFSTOPPED(st)); 234 ATF_REQUIRE(!WIFCONTINUED(st)); 235 ATF_REQUIRE(si.si_status == SIGQUIT); 236 ATF_REQUIRE(si.si_pid == pid); 237 ATF_REQUIRE(si.si_uid == getuid()); 238 ATF_REQUIRE(si.si_code == CLD_KILLED); 239 #ifdef __NetBSD__ 240 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 241 (uintmax_t)si.si_utime); 242 #endif 243 break; 244 } 245 } 246 247 ATF_TC(wait6_stopgo_loop); 248 ATF_TC_HEAD(wait6_stopgo_loop, tc) 249 { 250 atf_tc_set_md_var(tc, "descr", 251 "Test that wait6(2) handled stopped/continued process loop"); 252 } 253 254 ATF_TC_BODY(wait6_stopgo_loop, tc) 255 { 256 siginfo_t si; 257 struct wrusage wru; 258 int st; 259 pid_t pid; 260 static const struct rlimit rl = { 0, 0 }; 261 size_t N = 100; 262 263 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 264 switch (pid = fork()) { 265 case 0: 266 sleep(100); 267 /*FALLTHROUGH*/ 268 case -1: 269 ATF_REQUIRE(pid > 0); 270 } 271 272 printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N); 273 while (N --> 0) { 274 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 275 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 276 ATF_REQUIRE(!WIFEXITED(st)); 277 ATF_REQUIRE(!WIFSIGNALED(st)); 278 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 279 ATF_REQUIRE(!WIFCONTINUED(st)); 280 ATF_REQUIRE(si.si_status == SIGSTOP); 281 ATF_REQUIRE(si.si_pid == pid); 282 ATF_REQUIRE(si.si_uid == getuid()); 283 ATF_REQUIRE(si.si_code == CLD_STOPPED); 284 285 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 286 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 287 ATF_REQUIRE(!WIFEXITED(st)); 288 ATF_REQUIRE(!WIFSIGNALED(st)); 289 ATF_REQUIRE(WIFCONTINUED(st)); 290 ATF_REQUIRE(!WIFSTOPPED(st)); 291 ATF_REQUIRE(si.si_status == SIGCONT); 292 ATF_REQUIRE(si.si_pid == pid); 293 ATF_REQUIRE(si.si_uid == getuid()); 294 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 295 } 296 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 297 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 298 ATF_REQUIRE(!WIFEXITED(st)); 299 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 300 ATF_REQUIRE(!WIFSTOPPED(st)); 301 ATF_REQUIRE(!WIFCONTINUED(st)); 302 ATF_REQUIRE(si.si_status == SIGQUIT); 303 ATF_REQUIRE(si.si_pid == pid); 304 ATF_REQUIRE(si.si_uid == getuid()); 305 ATF_REQUIRE(si.si_code == CLD_KILLED); 306 #ifdef __NetBSD__ 307 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 308 (uintmax_t)si.si_utime); 309 #endif 310 } 311 312 ATF_TP_ADD_TCS(tp) 313 { 314 315 ATF_TP_ADD_TC(tp, wait6_invalid); 316 ATF_TP_ADD_TC(tp, wait6_exited); 317 ATF_TP_ADD_TC(tp, wait6_terminated); 318 ATF_TP_ADD_TC(tp, wait6_coredumped); 319 ATF_TP_ADD_TC(tp, wait6_stop_and_go); 320 ATF_TP_ADD_TC(tp, wait6_stopgo_loop); 321 322 return atf_no_error(); 323 } 324