t_wait.c revision 303980
1/* $NetBSD: t_wait.c,v 1.4 2016/04/27 21:14:24 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.4 2016/04/27 21:14:24 christos 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 47ATF_TC(wait6_invalid); 48ATF_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 54ATF_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 63ATF_TC(wait6_noproc); 64ATF_TC_HEAD(wait6_noproc, tc) 65{ 66 atf_tc_set_md_var(tc, "descr", 67 "Test that wait6(2) returns ECHILD with for no processes"); 68} 69 70ATF_TC_BODY(wait6_noproc, tc) 71{ 72 siginfo_t si; 73 struct wrusage wru; 74 int st; 75 ATF_REQUIRE(wait6(P_ALL, 0, &st, WEXITED, &wru, &si) == -1 76 && errno == ECHILD); 77} 78 79ATF_TC(wait6_exited); 80ATF_TC_HEAD(wait6_exited, tc) 81{ 82 atf_tc_set_md_var(tc, "descr", 83 "Test that wait6(2) handled exiting process and code"); 84} 85 86ATF_TC_BODY(wait6_exited, tc) 87{ 88 siginfo_t si; 89 struct wrusage wru; 90 int st; 91 pid_t pid; 92 93 switch (pid = fork()) { 94 case -1: 95 ATF_REQUIRE(pid > 0); 96 case 0: 97 exit(0x5a5a5a5a); 98 /*NOTREACHED*/ 99 default: 100 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 101 ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a); 102 ATF_REQUIRE(si.si_status = 0x5a5a5a5a); 103 ATF_REQUIRE(si.si_pid == pid); 104 ATF_REQUIRE(si.si_uid == getuid()); 105 ATF_REQUIRE(si.si_code == CLD_EXITED); 106 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 107 (uintmax_t)si.si_utime); 108 break; 109 } 110} 111 112ATF_TC(wait6_terminated); 113ATF_TC_HEAD(wait6_terminated, tc) 114{ 115 atf_tc_set_md_var(tc, "descr", 116 "Test that wait6(2) handled terminated process and code"); 117} 118 119ATF_TC_BODY(wait6_terminated, tc) 120{ 121 siginfo_t si; 122 struct wrusage wru; 123 int st; 124 pid_t pid; 125 126 switch (pid = fork()) { 127 case 0: 128 sleep(100); 129 /*FALLTHROUGH*/ 130 case -1: 131 ATF_REQUIRE(pid > 0); 132 default: 133 ATF_REQUIRE(kill(pid, SIGTERM) == 0); 134 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 135 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM); 136 ATF_REQUIRE(si.si_status == SIGTERM); 137 ATF_REQUIRE(si.si_pid == pid); 138 ATF_REQUIRE(si.si_uid == getuid()); 139 ATF_REQUIRE(si.si_code == CLD_KILLED); 140 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 141 (uintmax_t)si.si_utime); 142 break; 143 } 144} 145 146ATF_TC(wait6_coredumped); 147ATF_TC_HEAD(wait6_coredumped, tc) 148{ 149 atf_tc_set_md_var(tc, "descr", 150 "Test that wait6(2) handled coredumped process and code"); 151} 152 153ATF_TC_BODY(wait6_coredumped, tc) 154{ 155 siginfo_t si; 156 struct wrusage wru; 157 int st; 158 pid_t pid; 159 static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; 160 161 switch (pid = fork()) { 162 case 0: 163 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 164 *(char *)8 = 0; 165 /*FALLTHROUGH*/ 166 case -1: 167 ATF_REQUIRE(pid > 0); 168 default: 169 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 170 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV 171 && WCOREDUMP(st)); 172 ATF_REQUIRE(si.si_status == SIGSEGV); 173 ATF_REQUIRE(si.si_pid == pid); 174 ATF_REQUIRE(si.si_uid == getuid()); 175 ATF_REQUIRE(si.si_code == CLD_DUMPED); 176 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 177 (uintmax_t)si.si_utime); 178 break; 179 } 180} 181 182ATF_TC(wait6_stop_and_go); 183ATF_TC_HEAD(wait6_stop_and_go, tc) 184{ 185 atf_tc_set_md_var(tc, "descr", 186 "Test that wait6(2) handled stopped/continued process and code"); 187} 188 189ATF_TC_BODY(wait6_stop_and_go, tc) 190{ 191 siginfo_t si; 192 struct wrusage wru; 193 int st; 194 pid_t pid; 195 static const struct rlimit rl = { 0, 0 }; 196 197 ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0); 198 switch (pid = fork()) { 199 case 0: 200 sleep(100); 201 /*FALLTHROUGH*/ 202 case -1: 203 ATF_REQUIRE(pid > 0); 204 default: 205 ATF_REQUIRE(kill(pid, SIGSTOP) == 0); 206 ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid); 207 ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP); 208 ATF_REQUIRE(si.si_status == SIGSTOP); 209 ATF_REQUIRE(si.si_pid == pid); 210 ATF_REQUIRE(si.si_uid == getuid()); 211 ATF_REQUIRE(si.si_code == CLD_STOPPED); 212 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 213 (uintmax_t)si.si_utime); 214 215 ATF_REQUIRE(kill(pid, SIGCONT) == 0); 216 ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid); 217 ATF_REQUIRE(WIFCONTINUED(st)); 218 ATF_REQUIRE(si.si_status == SIGCONT); 219 ATF_REQUIRE(si.si_pid == pid); 220 ATF_REQUIRE(si.si_uid == getuid()); 221 ATF_REQUIRE(si.si_code == CLD_CONTINUED); 222 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 223 (uintmax_t)si.si_utime); 224 225 ATF_REQUIRE(kill(pid, SIGQUIT) == 0); 226 ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid); 227 ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT); 228 ATF_REQUIRE(si.si_status == SIGQUIT); 229 ATF_REQUIRE(si.si_pid == pid); 230 ATF_REQUIRE(si.si_uid == getuid()); 231 ATF_REQUIRE(si.si_code == CLD_KILLED); 232 printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime, 233 (uintmax_t)si.si_utime); 234 break; 235 } 236} 237 238ATF_TP_ADD_TCS(tp) 239{ 240 241 ATF_TP_ADD_TC(tp, wait6_invalid); 242 ATF_TP_ADD_TC(tp, wait6_noproc); 243 ATF_TP_ADD_TC(tp, wait6_exited); 244 ATF_TP_ADD_TC(tp, wait6_terminated); 245 ATF_TP_ADD_TC(tp, wait6_coredumped); 246 ATF_TP_ADD_TC(tp, wait6_stop_and_go); 247 248 return atf_no_error(); 249} 250