xref: /netbsd-src/tests/lib/libc/sys/t_wait.c (revision b025f918be4fe71eef58240db7abca767ee14999)
1*b025f918Smartin /* $NetBSD: t_wait.c,v 1.10 2021/07/17 14:03:35 martin Exp $ */
28283334aSchristos 
38283334aSchristos /*-
48283334aSchristos  * Copyright (c) 2016 The NetBSD Foundation, Inc.
58283334aSchristos  * All rights reserved.
68283334aSchristos  *
78283334aSchristos  * This code is derived from software contributed to The NetBSD Foundation
88283334aSchristos  * by Christos Zoulas.
98283334aSchristos  *
108283334aSchristos  * Redistribution and use in source and binary forms, with or without
118283334aSchristos  * modification, are permitted provided that the following conditions
128283334aSchristos  * are met:
138283334aSchristos  * 1. Redistributions of source code must retain the above copyright
148283334aSchristos  *    notice, this list of conditions and the following disclaimer.
158283334aSchristos  * 2. Redistributions in binary form must reproduce the above copyright
168283334aSchristos  *    notice, this list of conditions and the following disclaimer in the
178283334aSchristos  *    documentation and/or other materials provided with the distribution.
188283334aSchristos  *
198283334aSchristos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
208283334aSchristos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
218283334aSchristos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
228283334aSchristos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
238283334aSchristos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
248283334aSchristos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
258283334aSchristos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
268283334aSchristos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
278283334aSchristos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
288283334aSchristos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
298283334aSchristos  * POSSIBILITY OF SUCH DAMAGE.
308283334aSchristos  */
318283334aSchristos #include <sys/cdefs.h>
32*b025f918Smartin __RCSID("$NetBSD: t_wait.c,v 1.10 2021/07/17 14:03:35 martin Exp $");
338283334aSchristos 
348283334aSchristos #include <sys/wait.h>
358283334aSchristos #include <sys/resource.h>
368283334aSchristos 
378283334aSchristos #include <errno.h>
3886df5d0aSchristos #include <inttypes.h>
398283334aSchristos #include <limits.h>
408283334aSchristos #include <pwd.h>
418283334aSchristos #include <signal.h>
4286df5d0aSchristos #include <stdio.h>
438283334aSchristos #include <stdlib.h>
448283334aSchristos #include <unistd.h>
458283334aSchristos 
468283334aSchristos #include <atf-c.h>
478283334aSchristos 
488283334aSchristos ATF_TC(wait6_invalid);
ATF_TC_HEAD(wait6_invalid,tc)498283334aSchristos ATF_TC_HEAD(wait6_invalid, tc)
508283334aSchristos {
518283334aSchristos 	atf_tc_set_md_var(tc, "descr",
528283334aSchristos 	    "Test that wait6(2) returns EINVAL with 0 options");
538283334aSchristos }
548283334aSchristos 
ATF_TC_BODY(wait6_invalid,tc)558283334aSchristos ATF_TC_BODY(wait6_invalid, tc)
568283334aSchristos {
578283334aSchristos 	siginfo_t si;
588283334aSchristos 	struct wrusage wru;
598283334aSchristos 	int st;
608283334aSchristos 	ATF_REQUIRE(wait6(P_ALL, 0, &st, 0, &wru, &si) == -1
618283334aSchristos 	    && errno == EINVAL);
628283334aSchristos }
638283334aSchristos 
648283334aSchristos ATF_TC(wait6_exited);
ATF_TC_HEAD(wait6_exited,tc)658283334aSchristos ATF_TC_HEAD(wait6_exited, tc)
668283334aSchristos {
678283334aSchristos 	atf_tc_set_md_var(tc, "descr",
688283334aSchristos 	    "Test that wait6(2) handled exiting process and code");
698283334aSchristos }
708283334aSchristos 
ATF_TC_BODY(wait6_exited,tc)718283334aSchristos ATF_TC_BODY(wait6_exited, tc)
728283334aSchristos {
738283334aSchristos 	siginfo_t si;
748283334aSchristos 	struct wrusage wru;
758283334aSchristos 	int st;
768283334aSchristos 	pid_t pid;
778283334aSchristos 
788283334aSchristos 	switch (pid = fork()) {
798283334aSchristos 	case 0:
808283334aSchristos 		exit(0x5a5a5a5a);
818283334aSchristos 		/*NOTREACHED*/
82844d41bfSmrg 	case -1:
83844d41bfSmrg 		ATF_REQUIRE(pid > 0);
84844d41bfSmrg 		__unreachable();
858283334aSchristos 	default:
865befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid);
878283334aSchristos 		ATF_REQUIRE(WIFEXITED(st) && WEXITSTATUS(st) == 0x5a);
88*b025f918Smartin 		ATF_REQUIRE(si.si_status == 0x5a5a5a5a);
898283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
908283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
918283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_EXITED);
928283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
938283334aSchristos 		    (uintmax_t)si.si_utime);
948283334aSchristos 		break;
958283334aSchristos 	}
968283334aSchristos }
978283334aSchristos 
988283334aSchristos ATF_TC(wait6_terminated);
ATF_TC_HEAD(wait6_terminated,tc)998283334aSchristos ATF_TC_HEAD(wait6_terminated, tc)
1008283334aSchristos {
1018283334aSchristos 	atf_tc_set_md_var(tc, "descr",
1028283334aSchristos 	    "Test that wait6(2) handled terminated process and code");
1038283334aSchristos }
1048283334aSchristos 
ATF_TC_BODY(wait6_terminated,tc)1058283334aSchristos ATF_TC_BODY(wait6_terminated, tc)
1068283334aSchristos {
1078283334aSchristos 	siginfo_t si;
1088283334aSchristos 	struct wrusage wru;
1098283334aSchristos 	int st;
1108283334aSchristos 	pid_t pid;
1118283334aSchristos 
1128283334aSchristos 	switch (pid = fork()) {
1138283334aSchristos 	case 0:
1148283334aSchristos 		sleep(100);
1158283334aSchristos 		/*FALLTHROUGH*/
1168283334aSchristos 	case -1:
117bd76bbe6Schristos 		ATF_REQUIRE(pid > 0);
118844d41bfSmrg 		__unreachable();
1198283334aSchristos 	default:
1208283334aSchristos 		ATF_REQUIRE(kill(pid, SIGTERM) == 0);
1215befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid);
1228283334aSchristos 		ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGTERM);
1238283334aSchristos 		ATF_REQUIRE(si.si_status == SIGTERM);
1248283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
1258283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
1268283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_KILLED);
1278283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
1288283334aSchristos 		    (uintmax_t)si.si_utime);
1298283334aSchristos 		break;
1308283334aSchristos 	}
1318283334aSchristos }
1328283334aSchristos 
1338283334aSchristos ATF_TC(wait6_coredumped);
ATF_TC_HEAD(wait6_coredumped,tc)1348283334aSchristos ATF_TC_HEAD(wait6_coredumped, tc)
1358283334aSchristos {
1368283334aSchristos 	atf_tc_set_md_var(tc, "descr",
1378283334aSchristos 	    "Test that wait6(2) handled coredumped process and code");
1388283334aSchristos }
1398283334aSchristos 
ATF_TC_BODY(wait6_coredumped,tc)1408283334aSchristos ATF_TC_BODY(wait6_coredumped, tc)
1418283334aSchristos {
1428283334aSchristos 	siginfo_t si;
1438283334aSchristos 	struct wrusage wru;
1448283334aSchristos 	int st;
1458283334aSchristos 	pid_t pid;
1468283334aSchristos 	static const struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
1478283334aSchristos 
1488283334aSchristos 	switch (pid = fork()) {
1498283334aSchristos 	case 0:
1508283334aSchristos 		ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
1518283334aSchristos 		*(char *)8 = 0;
1528283334aSchristos 		/*FALLTHROUGH*/
1538283334aSchristos 	case -1:
154bd76bbe6Schristos 		ATF_REQUIRE(pid > 0);
155844d41bfSmrg 		__unreachable();
1568283334aSchristos 	default:
1575befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid);
1588283334aSchristos 		ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGSEGV
1598283334aSchristos 		    && WCOREDUMP(st));
1608283334aSchristos 		ATF_REQUIRE(si.si_status == SIGSEGV);
1618283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
1628283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
1638283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_DUMPED);
1648283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
1658283334aSchristos 		    (uintmax_t)si.si_utime);
1668283334aSchristos 		break;
1678283334aSchristos 	}
1688283334aSchristos }
1698283334aSchristos 
1708283334aSchristos ATF_TC(wait6_stop_and_go);
ATF_TC_HEAD(wait6_stop_and_go,tc)1718283334aSchristos ATF_TC_HEAD(wait6_stop_and_go, tc)
1728283334aSchristos {
1738283334aSchristos 	atf_tc_set_md_var(tc, "descr",
1748283334aSchristos 	    "Test that wait6(2) handled stopped/continued process and code");
1758283334aSchristos }
1768283334aSchristos 
ATF_TC_BODY(wait6_stop_and_go,tc)1778283334aSchristos ATF_TC_BODY(wait6_stop_and_go, tc)
1788283334aSchristos {
1798283334aSchristos 	siginfo_t si;
1808283334aSchristos 	struct wrusage wru;
1818283334aSchristos 	int st;
1828283334aSchristos 	pid_t pid;
1838283334aSchristos 	static const struct rlimit rl = { 0, 0 };
1848283334aSchristos 
1855befeffcSchristos 	ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
1868283334aSchristos 	switch (pid = fork()) {
1878283334aSchristos 	case 0:
1888283334aSchristos 		sleep(100);
1898283334aSchristos 		/*FALLTHROUGH*/
1908283334aSchristos 	case -1:
191bd76bbe6Schristos 		ATF_REQUIRE(pid > 0);
192844d41bfSmrg 		__unreachable();
1938283334aSchristos 	default:
1948283334aSchristos 		ATF_REQUIRE(kill(pid, SIGSTOP) == 0);
1955befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid);
19604949b41Skamil 		ATF_REQUIRE(!WIFEXITED(st));
19704949b41Skamil 		ATF_REQUIRE(!WIFSIGNALED(st));
1988283334aSchristos 		ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP);
19904949b41Skamil 		ATF_REQUIRE(!WIFCONTINUED(st));
2008283334aSchristos 		ATF_REQUIRE(si.si_status == SIGSTOP);
2018283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
2028283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
2038283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_STOPPED);
2048283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
2058283334aSchristos 		    (uintmax_t)si.si_utime);
2068283334aSchristos 
2078283334aSchristos 		ATF_REQUIRE(kill(pid, SIGCONT) == 0);
2085befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid);
20904949b41Skamil 		ATF_REQUIRE(!WIFEXITED(st));
21004949b41Skamil 		ATF_REQUIRE(!WIFSIGNALED(st));
211e533605fSchristos 		ATF_REQUIRE(WIFCONTINUED(st));
21204949b41Skamil 		ATF_REQUIRE(!WIFSTOPPED(st));
2138283334aSchristos 		ATF_REQUIRE(si.si_status == SIGCONT);
2148283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
2158283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
2168283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_CONTINUED);
2178283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
2188283334aSchristos 		    (uintmax_t)si.si_utime);
2198283334aSchristos 
2208283334aSchristos 		ATF_REQUIRE(kill(pid, SIGQUIT) == 0);
2215befeffcSchristos 		ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid);
22204949b41Skamil 		ATF_REQUIRE(!WIFEXITED(st));
2238283334aSchristos 		ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT);
22404949b41Skamil 		ATF_REQUIRE(!WIFSTOPPED(st));
22504949b41Skamil 		ATF_REQUIRE(!WIFCONTINUED(st));
2268283334aSchristos 		ATF_REQUIRE(si.si_status == SIGQUIT);
2278283334aSchristos 		ATF_REQUIRE(si.si_pid == pid);
2288283334aSchristos 		ATF_REQUIRE(si.si_uid == getuid());
2298283334aSchristos 		ATF_REQUIRE(si.si_code == CLD_KILLED);
2308283334aSchristos 		printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
2318283334aSchristos 		    (uintmax_t)si.si_utime);
2328283334aSchristos 		break;
2338283334aSchristos 	}
2348283334aSchristos }
2358283334aSchristos 
23604949b41Skamil ATF_TC(wait6_stopgo_loop);
ATF_TC_HEAD(wait6_stopgo_loop,tc)23704949b41Skamil ATF_TC_HEAD(wait6_stopgo_loop, tc)
23804949b41Skamil {
23904949b41Skamil 	atf_tc_set_md_var(tc, "descr",
24004949b41Skamil 	    "Test that wait6(2) handled stopped/continued process loop");
24104949b41Skamil }
24204949b41Skamil 
ATF_TC_BODY(wait6_stopgo_loop,tc)24304949b41Skamil ATF_TC_BODY(wait6_stopgo_loop, tc)
24404949b41Skamil {
24504949b41Skamil 	siginfo_t si;
24604949b41Skamil 	struct wrusage wru;
24704949b41Skamil 	int st;
24804949b41Skamil 	pid_t pid;
24904949b41Skamil 	static const struct rlimit rl = { 0, 0 };
25004949b41Skamil 	size_t N = 100;
25104949b41Skamil 
25204949b41Skamil 	ATF_REQUIRE(setrlimit(RLIMIT_CORE, &rl) == 0);
25304949b41Skamil 	switch (pid = fork()) {
25404949b41Skamil 	case 0:
25504949b41Skamil 		sleep(100);
25604949b41Skamil 		/*FALLTHROUGH*/
25704949b41Skamil 	case -1:
25804949b41Skamil 		ATF_REQUIRE(pid > 0);
259844d41bfSmrg 		__unreachable();
26004949b41Skamil 	}
26104949b41Skamil 
26204949b41Skamil 	printf("Before loop of SIGSTOP/SIGCONT sequence %zu times\n", N);
26304949b41Skamil 	while (N --> 0) {
26404949b41Skamil 		ATF_REQUIRE(kill(pid, SIGSTOP) == 0);
26504949b41Skamil 		ATF_REQUIRE(wait6(P_PID, pid, &st, WSTOPPED, &wru, &si) == pid);
26604949b41Skamil 		ATF_REQUIRE(!WIFEXITED(st));
26704949b41Skamil 		ATF_REQUIRE(!WIFSIGNALED(st));
26804949b41Skamil 		ATF_REQUIRE(WIFSTOPPED(st) && WSTOPSIG(st) == SIGSTOP);
26904949b41Skamil 		ATF_REQUIRE(!WIFCONTINUED(st));
27004949b41Skamil 		ATF_REQUIRE(si.si_status == SIGSTOP);
27104949b41Skamil 		ATF_REQUIRE(si.si_pid == pid);
27204949b41Skamil 		ATF_REQUIRE(si.si_uid == getuid());
27304949b41Skamil 		ATF_REQUIRE(si.si_code == CLD_STOPPED);
27404949b41Skamil 
27504949b41Skamil 		ATF_REQUIRE(kill(pid, SIGCONT) == 0);
27604949b41Skamil 		ATF_REQUIRE(wait6(P_PID, pid, &st, WCONTINUED, &wru, &si) == pid);
27704949b41Skamil 		ATF_REQUIRE(!WIFEXITED(st));
27804949b41Skamil 		ATF_REQUIRE(!WIFSIGNALED(st));
27904949b41Skamil 		ATF_REQUIRE(WIFCONTINUED(st));
28004949b41Skamil 		ATF_REQUIRE(!WIFSTOPPED(st));
28104949b41Skamil 		ATF_REQUIRE(si.si_status == SIGCONT);
28204949b41Skamil 		ATF_REQUIRE(si.si_pid == pid);
28304949b41Skamil 		ATF_REQUIRE(si.si_uid == getuid());
28404949b41Skamil 		ATF_REQUIRE(si.si_code == CLD_CONTINUED);
28504949b41Skamil 	}
28604949b41Skamil 	ATF_REQUIRE(kill(pid, SIGQUIT) == 0);
28704949b41Skamil 	ATF_REQUIRE(wait6(P_PID, pid, &st, WEXITED, &wru, &si) == pid);
28804949b41Skamil 	ATF_REQUIRE(!WIFEXITED(st));
28904949b41Skamil 	ATF_REQUIRE(WIFSIGNALED(st) && WTERMSIG(st) == SIGQUIT);
29004949b41Skamil 	ATF_REQUIRE(!WIFSTOPPED(st));
29104949b41Skamil 	ATF_REQUIRE(!WIFCONTINUED(st));
29204949b41Skamil 	ATF_REQUIRE(si.si_status == SIGQUIT);
29304949b41Skamil 	ATF_REQUIRE(si.si_pid == pid);
29404949b41Skamil 	ATF_REQUIRE(si.si_uid == getuid());
29504949b41Skamil 	ATF_REQUIRE(si.si_code == CLD_KILLED);
29604949b41Skamil 	printf("user: %ju system: %ju\n", (uintmax_t)si.si_utime,
29704949b41Skamil 	    (uintmax_t)si.si_utime);
29804949b41Skamil }
29904949b41Skamil 
ATF_TP_ADD_TCS(tp)3008283334aSchristos ATF_TP_ADD_TCS(tp)
3018283334aSchristos {
3028283334aSchristos 
3038283334aSchristos 	ATF_TP_ADD_TC(tp, wait6_invalid);
3048283334aSchristos 	ATF_TP_ADD_TC(tp, wait6_exited);
3058283334aSchristos 	ATF_TP_ADD_TC(tp, wait6_terminated);
3068283334aSchristos 	ATF_TP_ADD_TC(tp, wait6_coredumped);
3078283334aSchristos 	ATF_TP_ADD_TC(tp, wait6_stop_and_go);
30804949b41Skamil 	ATF_TP_ADD_TC(tp, wait6_stopgo_loop);
3098283334aSchristos 
3108283334aSchristos 	return atf_no_error();
3118283334aSchristos }
312