1128b9bf9SDmitry Chagin /*-
2128b9bf9SDmitry Chagin * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
3128b9bf9SDmitry Chagin *
4128b9bf9SDmitry Chagin * SPDX-License-Identifier: BSD-2-Clause
5128b9bf9SDmitry Chagin */
6128b9bf9SDmitry Chagin #include <sys/cdefs.h>
7128b9bf9SDmitry Chagin #include <sys/limits.h>
8128b9bf9SDmitry Chagin #include <sys/time.h>
9128b9bf9SDmitry Chagin #include <sys/sysctl.h>
10128b9bf9SDmitry Chagin #include <sys/user.h>
11128b9bf9SDmitry Chagin #include <sys/wait.h>
12128b9bf9SDmitry Chagin
13128b9bf9SDmitry Chagin #include <err.h>
14128b9bf9SDmitry Chagin #include <stdio.h>
15128b9bf9SDmitry Chagin #include <stdlib.h>
16128b9bf9SDmitry Chagin #include <string.h>
17128b9bf9SDmitry Chagin #include <errno.h>
18128b9bf9SDmitry Chagin #include <signal.h>
19128b9bf9SDmitry Chagin #include <stdbool.h>
20128b9bf9SDmitry Chagin #include <unistd.h>
21128b9bf9SDmitry Chagin
22128b9bf9SDmitry Chagin #include <atf-c.h>
23128b9bf9SDmitry Chagin
24128b9bf9SDmitry Chagin
25128b9bf9SDmitry Chagin static inline struct timespec
make_timespec(time_t s,long int ns)26128b9bf9SDmitry Chagin make_timespec(time_t s, long int ns)
27128b9bf9SDmitry Chagin {
28128b9bf9SDmitry Chagin struct timespec rts;
29128b9bf9SDmitry Chagin
30128b9bf9SDmitry Chagin rts.tv_sec = s;
31128b9bf9SDmitry Chagin rts.tv_nsec = ns;
32128b9bf9SDmitry Chagin return (rts);
33128b9bf9SDmitry Chagin }
34128b9bf9SDmitry Chagin
35128b9bf9SDmitry Chagin static void
dummy_sig_handler(int sig)36128b9bf9SDmitry Chagin dummy_sig_handler(int sig)
37128b9bf9SDmitry Chagin {
38128b9bf9SDmitry Chagin
39128b9bf9SDmitry Chagin }
40128b9bf9SDmitry Chagin
41128b9bf9SDmitry Chagin static void
dummy_sigchld(int signo,siginfo_t * info,void * ctx)42128b9bf9SDmitry Chagin dummy_sigchld(int signo, siginfo_t *info, void *ctx)
43128b9bf9SDmitry Chagin {
44128b9bf9SDmitry Chagin
45128b9bf9SDmitry Chagin }
46128b9bf9SDmitry Chagin
47128b9bf9SDmitry Chagin static void
support_signal(int sig,sig_t handler)48128b9bf9SDmitry Chagin support_signal(int sig, sig_t handler)
49128b9bf9SDmitry Chagin {
50128b9bf9SDmitry Chagin
51128b9bf9SDmitry Chagin ATF_REQUIRE(signal(sig, handler) != SIG_ERR);
52128b9bf9SDmitry Chagin }
53128b9bf9SDmitry Chagin
54128b9bf9SDmitry Chagin static void
support_sysctlset(const char * name,int32_t val)55128b9bf9SDmitry Chagin support_sysctlset(const char *name, int32_t val)
56128b9bf9SDmitry Chagin {
57128b9bf9SDmitry Chagin
58128b9bf9SDmitry Chagin ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0);
59128b9bf9SDmitry Chagin }
60128b9bf9SDmitry Chagin
61128b9bf9SDmitry Chagin static timer_t
support_create_timer(uint64_t sec,long int nsec,bool repeat,bool callback)62128b9bf9SDmitry Chagin support_create_timer(uint64_t sec, long int nsec, bool repeat,
63128b9bf9SDmitry Chagin bool callback)
64128b9bf9SDmitry Chagin {
65128b9bf9SDmitry Chagin struct sigevent ev = {
66128b9bf9SDmitry Chagin .sigev_notify = SIGEV_SIGNAL,
67128b9bf9SDmitry Chagin .sigev_signo = SIGALRM
68128b9bf9SDmitry Chagin };
69128b9bf9SDmitry Chagin struct itimerspec its =
70128b9bf9SDmitry Chagin {
71128b9bf9SDmitry Chagin { .tv_sec = repeat ? sec : 0, .tv_nsec = repeat ? nsec : 0 },
72128b9bf9SDmitry Chagin { .tv_sec = sec, .tv_nsec = nsec }
73128b9bf9SDmitry Chagin };
74128b9bf9SDmitry Chagin struct sigaction sa;
75128b9bf9SDmitry Chagin timer_t timerid;
76128b9bf9SDmitry Chagin
77128b9bf9SDmitry Chagin if (callback) {
78128b9bf9SDmitry Chagin sa.sa_handler = dummy_sig_handler;
79128b9bf9SDmitry Chagin sigemptyset (&sa.sa_mask);
80128b9bf9SDmitry Chagin sa.sa_flags = 0;
81128b9bf9SDmitry Chagin ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0);
82128b9bf9SDmitry Chagin }
83128b9bf9SDmitry Chagin ATF_REQUIRE(timer_create(CLOCK_REALTIME, &ev, &timerid) == 0);
84128b9bf9SDmitry Chagin ATF_REQUIRE(timer_settime(timerid, 0, &its, NULL) == 0);
85128b9bf9SDmitry Chagin return (timerid);
86128b9bf9SDmitry Chagin }
87128b9bf9SDmitry Chagin
88128b9bf9SDmitry Chagin static void
support_delete_timer(timer_t timer)89128b9bf9SDmitry Chagin support_delete_timer(timer_t timer)
90128b9bf9SDmitry Chagin {
91128b9bf9SDmitry Chagin
92128b9bf9SDmitry Chagin ATF_REQUIRE(timer_delete(timer) == 0);
93128b9bf9SDmitry Chagin support_signal(SIGALRM, SIG_DFL);
94128b9bf9SDmitry Chagin }
95128b9bf9SDmitry Chagin
96128b9bf9SDmitry Chagin static pid_t
support_create_sig_proc(int sig,int count,unsigned int usec)97128b9bf9SDmitry Chagin support_create_sig_proc(int sig, int count, unsigned int usec)
98128b9bf9SDmitry Chagin {
99128b9bf9SDmitry Chagin pid_t pid, cpid;
100128b9bf9SDmitry Chagin
101128b9bf9SDmitry Chagin pid = getpid();
102128b9bf9SDmitry Chagin ATF_REQUIRE(pid > 0);
103128b9bf9SDmitry Chagin cpid = fork();
104128b9bf9SDmitry Chagin ATF_REQUIRE(cpid >= 0);
105128b9bf9SDmitry Chagin
106128b9bf9SDmitry Chagin if (cpid == 0) {
107128b9bf9SDmitry Chagin while (count-- > 0) {
108128b9bf9SDmitry Chagin usleep(usec);
109128b9bf9SDmitry Chagin if (kill(pid, sig) == -1)
110128b9bf9SDmitry Chagin break;
111128b9bf9SDmitry Chagin }
112128b9bf9SDmitry Chagin exit(0);
113128b9bf9SDmitry Chagin }
114128b9bf9SDmitry Chagin return (cpid);
115128b9bf9SDmitry Chagin }
116128b9bf9SDmitry Chagin
117128b9bf9SDmitry Chagin #define TIMESPEC_HZ 1000000000
118128b9bf9SDmitry Chagin
119128b9bf9SDmitry Chagin static void
test_sigtimedwait_timeout_eagain(time_t sec,bool zero_tmo)120128b9bf9SDmitry Chagin test_sigtimedwait_timeout_eagain(time_t sec, bool zero_tmo)
121128b9bf9SDmitry Chagin {
122128b9bf9SDmitry Chagin struct timespec ts, timeout, now;
123128b9bf9SDmitry Chagin sigset_t ss;
124128b9bf9SDmitry Chagin int rv;
125128b9bf9SDmitry Chagin
126128b9bf9SDmitry Chagin ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
127128b9bf9SDmitry Chagin
128128b9bf9SDmitry Chagin timeout = make_timespec(sec, zero_tmo ? 0 : TIMESPEC_HZ/2);
129128b9bf9SDmitry Chagin timespecadd(&ts, &timeout, &ts);
130128b9bf9SDmitry Chagin
131128b9bf9SDmitry Chagin sigemptyset(&ss);
132128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
133128b9bf9SDmitry Chagin rv = sigtimedwait(&ss, NULL, &timeout);
134128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
135128b9bf9SDmitry Chagin "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
136128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
137128b9bf9SDmitry Chagin "sigtimedwait() should fail with EAGAIN: rv %d, errno %d",
138128b9bf9SDmitry Chagin rv, errno);
139128b9bf9SDmitry Chagin /* now >= ts */
140128b9bf9SDmitry Chagin ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
141128b9bf9SDmitry Chagin ATF_REQUIRE_MSG(timespeccmp(&now, &ts, >=) == true,
142*0ced2aefSDmitry Chagin "timespeccmp: now { %jd.%ld } < ts { %jd.%ld }",
143*0ced2aefSDmitry Chagin (intmax_t)now.tv_sec, now.tv_nsec,
144*0ced2aefSDmitry Chagin (intmax_t)ts.tv_sec, ts.tv_nsec);
145128b9bf9SDmitry Chagin }
146128b9bf9SDmitry Chagin
147128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_timeout_eagain0);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0,tc)148128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0, tc)
149128b9bf9SDmitry Chagin {
150128b9bf9SDmitry Chagin
151128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
152128b9bf9SDmitry Chagin }
153128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_timeout_eagain0,tc)154128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_timeout_eagain0, tc)
155128b9bf9SDmitry Chagin {
156128b9bf9SDmitry Chagin
157128b9bf9SDmitry Chagin test_sigtimedwait_timeout_eagain(0, true);
158128b9bf9SDmitry Chagin }
159128b9bf9SDmitry Chagin
160128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_timeout_eagain1);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1,tc)161128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1, tc)
162128b9bf9SDmitry Chagin {
163128b9bf9SDmitry Chagin
164128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
165128b9bf9SDmitry Chagin }
166128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_timeout_eagain1,tc)167128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_timeout_eagain1, tc)
168128b9bf9SDmitry Chagin {
169128b9bf9SDmitry Chagin
170128b9bf9SDmitry Chagin test_sigtimedwait_timeout_eagain(-1, true);
171128b9bf9SDmitry Chagin }
172128b9bf9SDmitry Chagin
173128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_timeout_eagain2);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2,tc)174128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2, tc)
175128b9bf9SDmitry Chagin {
176128b9bf9SDmitry Chagin
177128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
178128b9bf9SDmitry Chagin }
179128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_timeout_eagain2,tc)180128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_timeout_eagain2, tc)
181128b9bf9SDmitry Chagin {
182128b9bf9SDmitry Chagin
183128b9bf9SDmitry Chagin test_sigtimedwait_timeout_eagain(-1, false);
184128b9bf9SDmitry Chagin }
185128b9bf9SDmitry Chagin
186128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_timeout_eagain3);
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain3,tc)187128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_timeout_eagain3, tc)
188128b9bf9SDmitry Chagin {
189128b9bf9SDmitry Chagin
190128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits after specified timeout");
191128b9bf9SDmitry Chagin }
192128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_timeout_eagain3,tc)193128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_timeout_eagain3, tc)
194128b9bf9SDmitry Chagin {
195128b9bf9SDmitry Chagin
196128b9bf9SDmitry Chagin test_sigtimedwait_timeout_eagain(0, false);
197128b9bf9SDmitry Chagin }
198128b9bf9SDmitry Chagin
199128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_large_timeout_eintr);
ATF_TC_HEAD(test_sigtimedwait_large_timeout_eintr,tc)200128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_large_timeout_eintr, tc)
201128b9bf9SDmitry Chagin {
202128b9bf9SDmitry Chagin
203128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
204128b9bf9SDmitry Chagin }
205128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_large_timeout_eintr,tc)206128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_large_timeout_eintr, tc)
207128b9bf9SDmitry Chagin {
208128b9bf9SDmitry Chagin struct timespec ts;
209128b9bf9SDmitry Chagin timer_t timerid;
210128b9bf9SDmitry Chagin sigset_t ss;
211128b9bf9SDmitry Chagin int rv;
212128b9bf9SDmitry Chagin
213128b9bf9SDmitry Chagin ts = make_timespec(LONG_MAX, 0);
214128b9bf9SDmitry Chagin timerid = support_create_timer(0, 100000000, false, true);
215128b9bf9SDmitry Chagin
216128b9bf9SDmitry Chagin sigemptyset(&ss);
217128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
218128b9bf9SDmitry Chagin rv = sigtimedwait(&ss, NULL, &ts);
219128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
220128b9bf9SDmitry Chagin "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
221128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EINTR, errno,
222128b9bf9SDmitry Chagin "sigtimedwait() should fail with EINTR: rv %d, errno %d",
223128b9bf9SDmitry Chagin rv, errno);
224128b9bf9SDmitry Chagin support_delete_timer(timerid);
225128b9bf9SDmitry Chagin }
226128b9bf9SDmitry Chagin
227128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_infinity);
ATF_TC_HEAD(test_sigtimedwait_infinity,tc)228128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_infinity, tc)
229128b9bf9SDmitry Chagin {
230128b9bf9SDmitry Chagin
231128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
232128b9bf9SDmitry Chagin }
233128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_infinity,tc)234128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_infinity, tc)
235128b9bf9SDmitry Chagin {
236128b9bf9SDmitry Chagin timer_t timerid;
237128b9bf9SDmitry Chagin sigset_t ss;
238128b9bf9SDmitry Chagin int rv;
239128b9bf9SDmitry Chagin
240128b9bf9SDmitry Chagin timerid = support_create_timer(0, 100000000, false, true);
241128b9bf9SDmitry Chagin
242128b9bf9SDmitry Chagin sigemptyset(&ss);
243128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
244128b9bf9SDmitry Chagin rv = sigtimedwait(&ss, NULL, NULL);
245128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
246128b9bf9SDmitry Chagin "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
247128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EINTR, errno,
248128b9bf9SDmitry Chagin "sigtimedwait() should fail with EINTR: rv %d, errno %d",
249128b9bf9SDmitry Chagin rv, errno);
250128b9bf9SDmitry Chagin support_delete_timer(timerid);
251128b9bf9SDmitry Chagin }
252128b9bf9SDmitry Chagin
253128b9bf9SDmitry Chagin ATF_TC(test_sigtimedwait_einval);
ATF_TC_HEAD(test_sigtimedwait_einval,tc)254128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigtimedwait_einval, tc)
255128b9bf9SDmitry Chagin {
256128b9bf9SDmitry Chagin
257128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINVAL");
258128b9bf9SDmitry Chagin }
259128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigtimedwait_einval,tc)260128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigtimedwait_einval, tc)
261128b9bf9SDmitry Chagin {
262128b9bf9SDmitry Chagin struct timespec ts;
263128b9bf9SDmitry Chagin timer_t timerid;
264128b9bf9SDmitry Chagin sigset_t ss;
265128b9bf9SDmitry Chagin int rv;
266128b9bf9SDmitry Chagin
267128b9bf9SDmitry Chagin ts = make_timespec(0, -1);
268128b9bf9SDmitry Chagin timerid = support_create_timer(0, 100000000, false, true);
269128b9bf9SDmitry Chagin
270128b9bf9SDmitry Chagin sigemptyset(&ss);
271128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
272128b9bf9SDmitry Chagin rv = sigtimedwait(&ss, NULL, &ts);
273128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
274128b9bf9SDmitry Chagin "sigtimedwait () should fail: rv %d, errno %d", rv, errno);
275128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EINVAL, errno,
276128b9bf9SDmitry Chagin "sigtimedwait() should fail with EINVAL: rv %d, errno %d",
277128b9bf9SDmitry Chagin rv, errno);
278128b9bf9SDmitry Chagin support_delete_timer(timerid);
279128b9bf9SDmitry Chagin }
280128b9bf9SDmitry Chagin
281128b9bf9SDmitry Chagin ATF_TC(test_sigwait_eintr);
ATF_TC_HEAD(test_sigwait_eintr,tc)282128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigwait_eintr, tc)
283128b9bf9SDmitry Chagin {
284128b9bf9SDmitry Chagin
285128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigwait exits with EINTR");
286128b9bf9SDmitry Chagin }
287128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigwait_eintr,tc)288128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigwait_eintr, tc)
289128b9bf9SDmitry Chagin {
290128b9bf9SDmitry Chagin timer_t timerid;
291128b9bf9SDmitry Chagin sigset_t ss;
292128b9bf9SDmitry Chagin int rv, sig, pid;
293128b9bf9SDmitry Chagin
294128b9bf9SDmitry Chagin support_signal(SIGUSR1, dummy_sig_handler);
295128b9bf9SDmitry Chagin
296128b9bf9SDmitry Chagin pid = support_create_sig_proc(SIGUSR1, 1, 400000);
297128b9bf9SDmitry Chagin timerid = support_create_timer(0, 200000, false, true);
298128b9bf9SDmitry Chagin
299128b9bf9SDmitry Chagin sigemptyset(&ss);
300128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
301128b9bf9SDmitry Chagin rv = sigwait(&ss, &sig);
302128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(0, rv,
303128b9bf9SDmitry Chagin "sigwait() should not fail: rv %d, errno %d", rv, errno);
304128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(SIGUSR1, sig,
305128b9bf9SDmitry Chagin "sigwait() should return SIGUSR1: rv %d, sig %d", rv, sig);
306128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
307128b9bf9SDmitry Chagin support_delete_timer(timerid);
308128b9bf9SDmitry Chagin }
309128b9bf9SDmitry Chagin
310128b9bf9SDmitry Chagin ATF_TC(test_sigwaitinfo_eintr);
ATF_TC_HEAD(test_sigwaitinfo_eintr,tc)311128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sigwaitinfo_eintr, tc)
312128b9bf9SDmitry Chagin {
313128b9bf9SDmitry Chagin
314128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Check if sigwaitinfo exits with EINTR");
315128b9bf9SDmitry Chagin }
316128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sigwaitinfo_eintr,tc)317128b9bf9SDmitry Chagin ATF_TC_BODY(test_sigwaitinfo_eintr, tc)
318128b9bf9SDmitry Chagin {
319128b9bf9SDmitry Chagin timer_t timerid;
320128b9bf9SDmitry Chagin sigset_t ss;
321128b9bf9SDmitry Chagin int rv;
322128b9bf9SDmitry Chagin
323128b9bf9SDmitry Chagin timerid = support_create_timer(0, 100000000, false, true);
324128b9bf9SDmitry Chagin
325128b9bf9SDmitry Chagin sigemptyset(&ss);
326128b9bf9SDmitry Chagin sigaddset(&ss, SIGUSR1);
327128b9bf9SDmitry Chagin rv = sigwaitinfo(&ss, NULL);
328128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
329128b9bf9SDmitry Chagin "sigwaitinfo() should fail, rv %d != -1", rv);
330128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EINTR, errno,
331128b9bf9SDmitry Chagin "sigwaitinfo() should fail errno %d != EINTR", errno);
332128b9bf9SDmitry Chagin support_delete_timer(timerid);
333128b9bf9SDmitry Chagin }
334128b9bf9SDmitry Chagin
335128b9bf9SDmitry Chagin /*
336128b9bf9SDmitry Chagin * Test kern.sig_discard_ign knob (default true).
337128b9bf9SDmitry Chagin * See commit bc387624
338128b9bf9SDmitry Chagin */
339128b9bf9SDmitry Chagin static void
test_sig_discard_ign(bool ignore)340128b9bf9SDmitry Chagin test_sig_discard_ign(bool ignore)
341128b9bf9SDmitry Chagin {
342128b9bf9SDmitry Chagin struct timespec ts;
343128b9bf9SDmitry Chagin sigset_t mask;
344128b9bf9SDmitry Chagin pid_t pid;
345128b9bf9SDmitry Chagin int rv;
346128b9bf9SDmitry Chagin
347128b9bf9SDmitry Chagin support_signal(SIGUSR2, SIG_IGN);
348128b9bf9SDmitry Chagin
349128b9bf9SDmitry Chagin if (ignore)
350128b9bf9SDmitry Chagin support_sysctlset("kern.sig_discard_ign", 1);
351128b9bf9SDmitry Chagin else
352128b9bf9SDmitry Chagin support_sysctlset("kern.sig_discard_ign", 0);
353128b9bf9SDmitry Chagin
354128b9bf9SDmitry Chagin sigemptyset(&mask);
355128b9bf9SDmitry Chagin sigaddset(&mask, SIGUSR2);
356128b9bf9SDmitry Chagin ATF_REQUIRE(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
357128b9bf9SDmitry Chagin
358128b9bf9SDmitry Chagin pid = support_create_sig_proc(SIGUSR2, 1, 100000);
359128b9bf9SDmitry Chagin
360128b9bf9SDmitry Chagin ts = make_timespec(1, 0);
361128b9bf9SDmitry Chagin rv = sigtimedwait(&mask, NULL, &ts);
362128b9bf9SDmitry Chagin if (ignore == true) {
363128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, rv,
364128b9bf9SDmitry Chagin "sigtimedwait() ign=on should fail, rv %d != -1", rv);
365128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
366128b9bf9SDmitry Chagin "sigtimedwait() ign=on should fail with EAGAIN errno %d",
367128b9bf9SDmitry Chagin errno);
368128b9bf9SDmitry Chagin } else
369128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(SIGUSR2, rv,
370128b9bf9SDmitry Chagin "sigtimedwait() ign=off should return SIGUSR2, rv %d errno %d",
371128b9bf9SDmitry Chagin rv, errno);
372128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
373128b9bf9SDmitry Chagin }
374128b9bf9SDmitry Chagin
375128b9bf9SDmitry Chagin static void
support_check_siginfo(int code,int status,pid_t pid,siginfo_t * si,int sig)376128b9bf9SDmitry Chagin support_check_siginfo(int code, int status, pid_t pid,
377128b9bf9SDmitry Chagin siginfo_t *si, int sig)
378128b9bf9SDmitry Chagin {
379128b9bf9SDmitry Chagin
380128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(sig, si->si_signo,
381128b9bf9SDmitry Chagin "check_siginfo: si_signo %d != sig %d", si->si_signo, sig);
382128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(code, si->si_code,
383128b9bf9SDmitry Chagin "check_siginfo: si_code %d != code %d", si->si_code, code);
384128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(status, si->si_status,
385128b9bf9SDmitry Chagin "check_siginfo: si_status %d != status %d", si->si_status, status);
386128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(pid, si->si_pid,
387128b9bf9SDmitry Chagin "check_siginfo: si_pid %d != pid %d", si->si_pid, pid);
388128b9bf9SDmitry Chagin }
389128b9bf9SDmitry Chagin
390128b9bf9SDmitry Chagin static void
support_check_sigchld(sigset_t * set,int code,int status,pid_t pid,bool dequeue)391128b9bf9SDmitry Chagin support_check_sigchld(sigset_t *set, int code, int status, pid_t pid,
392128b9bf9SDmitry Chagin bool dequeue)
393128b9bf9SDmitry Chagin {
394128b9bf9SDmitry Chagin siginfo_t si;
395128b9bf9SDmitry Chagin int sig, kpid;
396128b9bf9SDmitry Chagin
397128b9bf9SDmitry Chagin if (dequeue == true)
398128b9bf9SDmitry Chagin kpid = support_create_sig_proc(SIGUSR2, 1, 1000000);
399128b9bf9SDmitry Chagin
400128b9bf9SDmitry Chagin sig = sigwaitinfo(set, &si);
401128b9bf9SDmitry Chagin if (dequeue == true) {
402128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(-1, sig,
403128b9bf9SDmitry Chagin "sigwaitinfo() should fail, sig %d != -1", sig);
404128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(EINTR, errno,
405128b9bf9SDmitry Chagin "sigwaitinfo() should fail errno %d != EINTR", errno);
406128b9bf9SDmitry Chagin } else
407128b9bf9SDmitry Chagin ATF_REQUIRE_EQ_MSG(SIGCHLD, sig,
408128b9bf9SDmitry Chagin "sigwaitinfo() %d != SIGCHLD", sig);
409128b9bf9SDmitry Chagin if (dequeue == false)
410128b9bf9SDmitry Chagin support_check_siginfo(code, status, pid, &si, SIGCHLD);
411128b9bf9SDmitry Chagin if (dequeue == true)
412128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, kpid, &si, WEXITED) == 0);
413128b9bf9SDmitry Chagin }
414128b9bf9SDmitry Chagin
415128b9bf9SDmitry Chagin static void
test_child(void)416128b9bf9SDmitry Chagin test_child(void)
417128b9bf9SDmitry Chagin {
418128b9bf9SDmitry Chagin
419128b9bf9SDmitry Chagin raise(SIGSTOP);
420128b9bf9SDmitry Chagin while (1)
421128b9bf9SDmitry Chagin pause();
422128b9bf9SDmitry Chagin }
423128b9bf9SDmitry Chagin
424128b9bf9SDmitry Chagin /*
425128b9bf9SDmitry Chagin * Test kern.wait_dequeue_sigchld knob.
426128b9bf9SDmitry Chagin */
427128b9bf9SDmitry Chagin static void
test_wait_dequeue_sigchld(bool dequeue)428128b9bf9SDmitry Chagin test_wait_dequeue_sigchld(bool dequeue)
429128b9bf9SDmitry Chagin {
430128b9bf9SDmitry Chagin struct sigaction sa;
431128b9bf9SDmitry Chagin siginfo_t si;
432128b9bf9SDmitry Chagin sigset_t set;
433128b9bf9SDmitry Chagin pid_t pid;
434128b9bf9SDmitry Chagin
435128b9bf9SDmitry Chagin sa.sa_flags = SA_SIGINFO | SA_RESTART;
436128b9bf9SDmitry Chagin sa.sa_sigaction = dummy_sigchld;
437128b9bf9SDmitry Chagin sigemptyset(&sa.sa_mask);
438128b9bf9SDmitry Chagin ATF_REQUIRE(sigaction(SIGCHLD, &sa, NULL) == 0);
439128b9bf9SDmitry Chagin
440128b9bf9SDmitry Chagin support_signal(SIGUSR2, dummy_sig_handler);
441128b9bf9SDmitry Chagin
442128b9bf9SDmitry Chagin sigemptyset(&set);
443128b9bf9SDmitry Chagin sigaddset(&set, SIGCHLD);
444128b9bf9SDmitry Chagin ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
445128b9bf9SDmitry Chagin
446128b9bf9SDmitry Chagin if (dequeue)
447128b9bf9SDmitry Chagin support_sysctlset("kern.wait_dequeue_sigchld", 1);
448128b9bf9SDmitry Chagin else
449128b9bf9SDmitry Chagin support_sysctlset("kern.wait_dequeue_sigchld", 0);
450128b9bf9SDmitry Chagin
451128b9bf9SDmitry Chagin pid = fork();
452128b9bf9SDmitry Chagin ATF_REQUIRE(pid >= 0);
453128b9bf9SDmitry Chagin if (pid == 0) {
454128b9bf9SDmitry Chagin test_child();
455128b9bf9SDmitry Chagin exit(0);
456128b9bf9SDmitry Chagin }
457128b9bf9SDmitry Chagin
458128b9bf9SDmitry Chagin bzero(&si, sizeof(si));
459128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, pid, &si, WSTOPPED) == 0);
460128b9bf9SDmitry Chagin
461128b9bf9SDmitry Chagin support_check_siginfo(CLD_STOPPED, SIGSTOP, pid, &si, SIGCHLD);
462128b9bf9SDmitry Chagin support_check_sigchld(&set, CLD_STOPPED, SIGSTOP, pid, dequeue);
463128b9bf9SDmitry Chagin
464128b9bf9SDmitry Chagin ATF_REQUIRE(kill(pid, SIGCONT) == 0);
465128b9bf9SDmitry Chagin
466128b9bf9SDmitry Chagin bzero(&si, sizeof(si));
467128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, pid, &si, WCONTINUED) == 0);
468128b9bf9SDmitry Chagin
469128b9bf9SDmitry Chagin support_check_siginfo(CLD_CONTINUED, SIGCONT, pid, &si, SIGCHLD);
470128b9bf9SDmitry Chagin support_check_sigchld(&set, CLD_CONTINUED, SIGCONT, pid, dequeue);
471128b9bf9SDmitry Chagin
472128b9bf9SDmitry Chagin ATF_REQUIRE(kill(pid, SIGKILL) == 0);
473128b9bf9SDmitry Chagin
474128b9bf9SDmitry Chagin bzero(&si, sizeof(si));
475128b9bf9SDmitry Chagin ATF_REQUIRE(waitid(P_PID, pid, &si, WEXITED) == 0);
476128b9bf9SDmitry Chagin
477128b9bf9SDmitry Chagin support_check_siginfo(CLD_KILLED, SIGKILL, pid, &si, SIGCHLD);
478128b9bf9SDmitry Chagin }
479128b9bf9SDmitry Chagin
480128b9bf9SDmitry Chagin ATF_TC_WITH_CLEANUP(test_sig_discard_ign_true);
ATF_TC_HEAD(test_sig_discard_ign_true,tc)481128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sig_discard_ign_true, tc)
482128b9bf9SDmitry Chagin {
483128b9bf9SDmitry Chagin
484128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
485128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign on");
486128b9bf9SDmitry Chagin }
487128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sig_discard_ign_true,tc)488128b9bf9SDmitry Chagin ATF_TC_BODY(test_sig_discard_ign_true, tc)
489128b9bf9SDmitry Chagin {
490128b9bf9SDmitry Chagin
491128b9bf9SDmitry Chagin test_sig_discard_ign(true);
492128b9bf9SDmitry Chagin }
493128b9bf9SDmitry Chagin
ATF_TC_CLEANUP(test_sig_discard_ign_true,tc)494128b9bf9SDmitry Chagin ATF_TC_CLEANUP(test_sig_discard_ign_true, tc)
495128b9bf9SDmitry Chagin {
496128b9bf9SDmitry Chagin
497128b9bf9SDmitry Chagin support_sysctlset("kern.sig_discard_ign", 1);
498128b9bf9SDmitry Chagin }
499128b9bf9SDmitry Chagin
500128b9bf9SDmitry Chagin ATF_TC_WITH_CLEANUP(test_sig_discard_ign_false);
ATF_TC_HEAD(test_sig_discard_ign_false,tc)501128b9bf9SDmitry Chagin ATF_TC_HEAD(test_sig_discard_ign_false, tc)
502128b9bf9SDmitry Chagin {
503128b9bf9SDmitry Chagin
504128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
505128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign off");
506128b9bf9SDmitry Chagin }
507128b9bf9SDmitry Chagin
ATF_TC_BODY(test_sig_discard_ign_false,tc)508128b9bf9SDmitry Chagin ATF_TC_BODY(test_sig_discard_ign_false, tc)
509128b9bf9SDmitry Chagin {
510128b9bf9SDmitry Chagin
511128b9bf9SDmitry Chagin test_sig_discard_ign(false);
512128b9bf9SDmitry Chagin }
513128b9bf9SDmitry Chagin
ATF_TC_CLEANUP(test_sig_discard_ign_false,tc)514128b9bf9SDmitry Chagin ATF_TC_CLEANUP(test_sig_discard_ign_false, tc)
515128b9bf9SDmitry Chagin {
516128b9bf9SDmitry Chagin
517128b9bf9SDmitry Chagin support_sysctlset("kern.sig_discard_ign", 1);
518128b9bf9SDmitry Chagin }
519128b9bf9SDmitry Chagin
520128b9bf9SDmitry Chagin ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_true);
ATF_TC_HEAD(test_wait_dequeue_sigchld_true,tc)521128b9bf9SDmitry Chagin ATF_TC_HEAD(test_wait_dequeue_sigchld_true, tc)
522128b9bf9SDmitry Chagin {
523128b9bf9SDmitry Chagin
524128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
525128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld on");
526128b9bf9SDmitry Chagin }
527128b9bf9SDmitry Chagin
ATF_TC_BODY(test_wait_dequeue_sigchld_true,tc)528128b9bf9SDmitry Chagin ATF_TC_BODY(test_wait_dequeue_sigchld_true, tc)
529128b9bf9SDmitry Chagin {
530128b9bf9SDmitry Chagin
531128b9bf9SDmitry Chagin test_wait_dequeue_sigchld(true);
532128b9bf9SDmitry Chagin }
533128b9bf9SDmitry Chagin
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true,tc)534128b9bf9SDmitry Chagin ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true, tc)
535128b9bf9SDmitry Chagin {
536128b9bf9SDmitry Chagin
537128b9bf9SDmitry Chagin support_sysctlset("kern.wait_dequeue_sigchld", 1);
538128b9bf9SDmitry Chagin }
539128b9bf9SDmitry Chagin
540128b9bf9SDmitry Chagin ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_false);
ATF_TC_HEAD(test_wait_dequeue_sigchld_false,tc)541128b9bf9SDmitry Chagin ATF_TC_HEAD(test_wait_dequeue_sigchld_false, tc)
542128b9bf9SDmitry Chagin {
543128b9bf9SDmitry Chagin
544128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "require.user", "root");
545128b9bf9SDmitry Chagin atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld off");
546128b9bf9SDmitry Chagin }
547128b9bf9SDmitry Chagin
ATF_TC_BODY(test_wait_dequeue_sigchld_false,tc)548128b9bf9SDmitry Chagin ATF_TC_BODY(test_wait_dequeue_sigchld_false, tc)
549128b9bf9SDmitry Chagin {
550128b9bf9SDmitry Chagin
551128b9bf9SDmitry Chagin test_wait_dequeue_sigchld(false);
552128b9bf9SDmitry Chagin }
553128b9bf9SDmitry Chagin
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false,tc)554128b9bf9SDmitry Chagin ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false, tc)
555128b9bf9SDmitry Chagin {
556128b9bf9SDmitry Chagin
557128b9bf9SDmitry Chagin support_sysctlset("kern.wait_dequeue_sigchld", 1);
558128b9bf9SDmitry Chagin }
559128b9bf9SDmitry Chagin
ATF_TP_ADD_TCS(tp)560128b9bf9SDmitry Chagin ATF_TP_ADD_TCS(tp)
561128b9bf9SDmitry Chagin {
562128b9bf9SDmitry Chagin
563128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain0);
564128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain1);
565128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain2);
566128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain3);
567128b9bf9SDmitry Chagin
568128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_large_timeout_eintr);
569128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_infinity);
570128b9bf9SDmitry Chagin
571128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigtimedwait_einval);
572128b9bf9SDmitry Chagin
573128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigwait_eintr);
574128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sigwaitinfo_eintr);
575128b9bf9SDmitry Chagin
576128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sig_discard_ign_true);
577128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_sig_discard_ign_false);
578128b9bf9SDmitry Chagin
579128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_true);
580128b9bf9SDmitry Chagin ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_false);
581128b9bf9SDmitry Chagin
582128b9bf9SDmitry Chagin return (atf_no_error());
583128b9bf9SDmitry Chagin }
584