t_wait.c revision 1.7 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