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