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