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