xref: /freebsd/contrib/netbsd-tests/lib/libc/sys/t_wait.c (revision 8a6fe8ce60ab99778558c4951d23615a0141daf0)
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