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