Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/sigwait.c
39536 views
1
/*-
2
* Copyright (c) 2022 Dmitry Chagin <[email protected]>
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
#include <sys/cdefs.h>
7
#include <sys/limits.h>
8
#include <sys/time.h>
9
#include <sys/sysctl.h>
10
#include <sys/user.h>
11
#include <sys/wait.h>
12
13
#include <err.h>
14
#include <stdio.h>
15
#include <stdlib.h>
16
#include <string.h>
17
#include <errno.h>
18
#include <signal.h>
19
#include <stdbool.h>
20
#include <unistd.h>
21
22
#include <atf-c.h>
23
24
25
static inline struct timespec
26
make_timespec(time_t s, long int ns)
27
{
28
struct timespec rts;
29
30
rts.tv_sec = s;
31
rts.tv_nsec = ns;
32
return (rts);
33
}
34
35
static void
36
dummy_sig_handler(int sig)
37
{
38
39
}
40
41
static void
42
dummy_sigchld(int signo, siginfo_t *info, void *ctx)
43
{
44
45
}
46
47
static void
48
support_signal(int sig, sig_t handler)
49
{
50
51
ATF_REQUIRE(signal(sig, handler) != SIG_ERR);
52
}
53
54
static void
55
support_sysctlset(const char *name, int32_t val)
56
{
57
58
ATF_REQUIRE(sysctlbyname(name, NULL, NULL, &val, sizeof(val)) == 0);
59
}
60
61
static timer_t
62
support_create_timer(uint64_t sec, long int nsec, bool repeat,
63
bool callback)
64
{
65
struct sigevent ev = {
66
.sigev_notify = SIGEV_SIGNAL,
67
.sigev_signo = SIGALRM
68
};
69
struct itimerspec its =
70
{
71
{ .tv_sec = repeat ? sec : 0, .tv_nsec = repeat ? nsec : 0 },
72
{ .tv_sec = sec, .tv_nsec = nsec }
73
};
74
struct sigaction sa;
75
timer_t timerid;
76
77
if (callback) {
78
sa.sa_handler = dummy_sig_handler;
79
sigemptyset (&sa.sa_mask);
80
sa.sa_flags = 0;
81
ATF_REQUIRE(sigaction(SIGALRM, &sa, NULL) == 0);
82
}
83
ATF_REQUIRE(timer_create(CLOCK_REALTIME, &ev, &timerid) == 0);
84
ATF_REQUIRE(timer_settime(timerid, 0, &its, NULL) == 0);
85
return (timerid);
86
}
87
88
static void
89
support_delete_timer(timer_t timer)
90
{
91
92
ATF_REQUIRE(timer_delete(timer) == 0);
93
support_signal(SIGALRM, SIG_DFL);
94
}
95
96
static pid_t
97
support_create_sig_proc(int sig, int count, unsigned int usec)
98
{
99
pid_t pid, cpid;
100
101
pid = getpid();
102
ATF_REQUIRE(pid > 0);
103
cpid = fork();
104
ATF_REQUIRE(cpid >= 0);
105
106
if (cpid == 0) {
107
while (count-- > 0) {
108
usleep(usec);
109
if (kill(pid, sig) == -1)
110
break;
111
}
112
exit(0);
113
}
114
return (cpid);
115
}
116
117
#define TIMESPEC_HZ 1000000000
118
119
static void
120
test_sigtimedwait_timeout_eagain(time_t sec, bool zero_tmo)
121
{
122
struct timespec ts, timeout, now;
123
sigset_t ss;
124
int rv;
125
126
ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
127
128
timeout = make_timespec(sec, zero_tmo ? 0 : TIMESPEC_HZ/2);
129
timespecadd(&ts, &timeout, &ts);
130
131
sigemptyset(&ss);
132
sigaddset(&ss, SIGUSR1);
133
rv = sigtimedwait(&ss, NULL, &timeout);
134
ATF_REQUIRE_EQ_MSG(-1, rv,
135
"sigtimedwait () should fail: rv %d, errno %d", rv, errno);
136
ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
137
"sigtimedwait() should fail with EAGAIN: rv %d, errno %d",
138
rv, errno);
139
/* now >= ts */
140
ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &now) == 0);
141
ATF_REQUIRE_MSG(timespeccmp(&now, &ts, >=) == true,
142
"timespeccmp: now { %jd.%ld } < ts { %jd.%ld }",
143
(intmax_t)now.tv_sec, now.tv_nsec,
144
(intmax_t)ts.tv_sec, ts.tv_nsec);
145
}
146
147
ATF_TC(test_sigtimedwait_timeout_eagain0);
148
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain0, tc)
149
{
150
151
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
152
}
153
154
ATF_TC_BODY(test_sigtimedwait_timeout_eagain0, tc)
155
{
156
157
test_sigtimedwait_timeout_eagain(0, true);
158
}
159
160
ATF_TC(test_sigtimedwait_timeout_eagain1);
161
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain1, tc)
162
{
163
164
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
165
}
166
167
ATF_TC_BODY(test_sigtimedwait_timeout_eagain1, tc)
168
{
169
170
test_sigtimedwait_timeout_eagain(-1, true);
171
}
172
173
ATF_TC(test_sigtimedwait_timeout_eagain2);
174
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain2, tc)
175
{
176
177
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits immediately");
178
}
179
180
ATF_TC_BODY(test_sigtimedwait_timeout_eagain2, tc)
181
{
182
183
test_sigtimedwait_timeout_eagain(-1, false);
184
}
185
186
ATF_TC(test_sigtimedwait_timeout_eagain3);
187
ATF_TC_HEAD(test_sigtimedwait_timeout_eagain3, tc)
188
{
189
190
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits after specified timeout");
191
}
192
193
ATF_TC_BODY(test_sigtimedwait_timeout_eagain3, tc)
194
{
195
196
test_sigtimedwait_timeout_eagain(0, false);
197
}
198
199
ATF_TC(test_sigtimedwait_large_timeout_eintr);
200
ATF_TC_HEAD(test_sigtimedwait_large_timeout_eintr, tc)
201
{
202
203
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
204
}
205
206
ATF_TC_BODY(test_sigtimedwait_large_timeout_eintr, tc)
207
{
208
struct timespec ts;
209
timer_t timerid;
210
sigset_t ss;
211
int rv;
212
213
ts = make_timespec(LONG_MAX, 0);
214
timerid = support_create_timer(0, 100000000, false, true);
215
216
sigemptyset(&ss);
217
sigaddset(&ss, SIGUSR1);
218
rv = sigtimedwait(&ss, NULL, &ts);
219
ATF_REQUIRE_EQ_MSG(-1, rv,
220
"sigtimedwait () should fail: rv %d, errno %d", rv, errno);
221
ATF_REQUIRE_EQ_MSG(EINTR, errno,
222
"sigtimedwait() should fail with EINTR: rv %d, errno %d",
223
rv, errno);
224
support_delete_timer(timerid);
225
}
226
227
ATF_TC(test_sigtimedwait_infinity);
228
ATF_TC_HEAD(test_sigtimedwait_infinity, tc)
229
{
230
231
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINTR");
232
}
233
234
ATF_TC_BODY(test_sigtimedwait_infinity, tc)
235
{
236
timer_t timerid;
237
sigset_t ss;
238
int rv;
239
240
timerid = support_create_timer(0, 100000000, false, true);
241
242
sigemptyset(&ss);
243
sigaddset(&ss, SIGUSR1);
244
rv = sigtimedwait(&ss, NULL, NULL);
245
ATF_REQUIRE_EQ_MSG(-1, rv,
246
"sigtimedwait () should fail: rv %d, errno %d", rv, errno);
247
ATF_REQUIRE_EQ_MSG(EINTR, errno,
248
"sigtimedwait() should fail with EINTR: rv %d, errno %d",
249
rv, errno);
250
support_delete_timer(timerid);
251
}
252
253
ATF_TC(test_sigtimedwait_einval);
254
ATF_TC_HEAD(test_sigtimedwait_einval, tc)
255
{
256
257
atf_tc_set_md_var(tc, "descr", "Check if sigtimedwait exits with EINVAL");
258
}
259
260
ATF_TC_BODY(test_sigtimedwait_einval, tc)
261
{
262
struct timespec ts;
263
timer_t timerid;
264
sigset_t ss;
265
int rv;
266
267
ts = make_timespec(0, -1);
268
timerid = support_create_timer(0, 100000000, false, true);
269
270
sigemptyset(&ss);
271
sigaddset(&ss, SIGUSR1);
272
rv = sigtimedwait(&ss, NULL, &ts);
273
ATF_REQUIRE_EQ_MSG(-1, rv,
274
"sigtimedwait () should fail: rv %d, errno %d", rv, errno);
275
ATF_REQUIRE_EQ_MSG(EINVAL, errno,
276
"sigtimedwait() should fail with EINVAL: rv %d, errno %d",
277
rv, errno);
278
support_delete_timer(timerid);
279
}
280
281
ATF_TC(test_sigwait_eintr);
282
ATF_TC_HEAD(test_sigwait_eintr, tc)
283
{
284
285
atf_tc_set_md_var(tc, "descr", "Check if sigwait exits with EINTR");
286
}
287
288
ATF_TC_BODY(test_sigwait_eintr, tc)
289
{
290
timer_t timerid;
291
sigset_t ss;
292
int rv, sig, pid;
293
294
support_signal(SIGUSR1, dummy_sig_handler);
295
296
pid = support_create_sig_proc(SIGUSR1, 1, 400000);
297
timerid = support_create_timer(0, 200000, false, true);
298
299
sigemptyset(&ss);
300
sigaddset(&ss, SIGUSR1);
301
rv = sigwait(&ss, &sig);
302
ATF_REQUIRE_EQ_MSG(0, rv,
303
"sigwait() should not fail: rv %d, errno %d", rv, errno);
304
ATF_REQUIRE_EQ_MSG(SIGUSR1, sig,
305
"sigwait() should return SIGUSR1: rv %d, sig %d", rv, sig);
306
ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
307
support_delete_timer(timerid);
308
}
309
310
ATF_TC(test_sigwaitinfo_eintr);
311
ATF_TC_HEAD(test_sigwaitinfo_eintr, tc)
312
{
313
314
atf_tc_set_md_var(tc, "descr", "Check if sigwaitinfo exits with EINTR");
315
}
316
317
ATF_TC_BODY(test_sigwaitinfo_eintr, tc)
318
{
319
timer_t timerid;
320
sigset_t ss;
321
int rv;
322
323
timerid = support_create_timer(0, 100000000, false, true);
324
325
sigemptyset(&ss);
326
sigaddset(&ss, SIGUSR1);
327
rv = sigwaitinfo(&ss, NULL);
328
ATF_REQUIRE_EQ_MSG(-1, rv,
329
"sigwaitinfo() should fail, rv %d != -1", rv);
330
ATF_REQUIRE_EQ_MSG(EINTR, errno,
331
"sigwaitinfo() should fail errno %d != EINTR", errno);
332
support_delete_timer(timerid);
333
}
334
335
/*
336
* Test kern.sig_discard_ign knob (default true).
337
* See commit bc387624
338
*/
339
static void
340
test_sig_discard_ign(bool ignore)
341
{
342
struct timespec ts;
343
sigset_t mask;
344
pid_t pid;
345
int rv;
346
347
support_signal(SIGUSR2, SIG_IGN);
348
349
if (ignore)
350
support_sysctlset("kern.sig_discard_ign", 1);
351
else
352
support_sysctlset("kern.sig_discard_ign", 0);
353
354
sigemptyset(&mask);
355
sigaddset(&mask, SIGUSR2);
356
ATF_REQUIRE(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
357
358
pid = support_create_sig_proc(SIGUSR2, 1, 100000);
359
360
ts = make_timespec(1, 0);
361
rv = sigtimedwait(&mask, NULL, &ts);
362
if (ignore == true) {
363
ATF_REQUIRE_EQ_MSG(-1, rv,
364
"sigtimedwait() ign=on should fail, rv %d != -1", rv);
365
ATF_REQUIRE_EQ_MSG(EAGAIN, errno,
366
"sigtimedwait() ign=on should fail with EAGAIN errno %d",
367
errno);
368
} else
369
ATF_REQUIRE_EQ_MSG(SIGUSR2, rv,
370
"sigtimedwait() ign=off should return SIGUSR2, rv %d errno %d",
371
rv, errno);
372
ATF_REQUIRE(waitid(P_PID, pid, NULL, WEXITED) == 0);
373
}
374
375
static void
376
support_check_siginfo(int code, int status, pid_t pid,
377
siginfo_t *si, int sig)
378
{
379
380
ATF_REQUIRE_EQ_MSG(sig, si->si_signo,
381
"check_siginfo: si_signo %d != sig %d", si->si_signo, sig);
382
ATF_REQUIRE_EQ_MSG(code, si->si_code,
383
"check_siginfo: si_code %d != code %d", si->si_code, code);
384
ATF_REQUIRE_EQ_MSG(status, si->si_status,
385
"check_siginfo: si_status %d != status %d", si->si_status, status);
386
ATF_REQUIRE_EQ_MSG(pid, si->si_pid,
387
"check_siginfo: si_pid %d != pid %d", si->si_pid, pid);
388
}
389
390
static void
391
support_check_sigchld(sigset_t *set, int code, int status, pid_t pid,
392
bool dequeue)
393
{
394
siginfo_t si;
395
int sig, kpid;
396
397
if (dequeue == true)
398
kpid = support_create_sig_proc(SIGUSR2, 1, 1000000);
399
400
sig = sigwaitinfo(set, &si);
401
if (dequeue == true) {
402
ATF_REQUIRE_EQ_MSG(-1, sig,
403
"sigwaitinfo() should fail, sig %d != -1", sig);
404
ATF_REQUIRE_EQ_MSG(EINTR, errno,
405
"sigwaitinfo() should fail errno %d != EINTR", errno);
406
} else
407
ATF_REQUIRE_EQ_MSG(SIGCHLD, sig,
408
"sigwaitinfo() %d != SIGCHLD", sig);
409
if (dequeue == false)
410
support_check_siginfo(code, status, pid, &si, SIGCHLD);
411
if (dequeue == true)
412
ATF_REQUIRE(waitid(P_PID, kpid, &si, WEXITED) == 0);
413
}
414
415
static void
416
test_child(void)
417
{
418
419
raise(SIGSTOP);
420
while (1)
421
pause();
422
}
423
424
/*
425
* Test kern.wait_dequeue_sigchld knob.
426
*/
427
static void
428
test_wait_dequeue_sigchld(bool dequeue)
429
{
430
struct sigaction sa;
431
siginfo_t si;
432
sigset_t set;
433
pid_t pid;
434
435
sa.sa_flags = SA_SIGINFO | SA_RESTART;
436
sa.sa_sigaction = dummy_sigchld;
437
sigemptyset(&sa.sa_mask);
438
ATF_REQUIRE(sigaction(SIGCHLD, &sa, NULL) == 0);
439
440
support_signal(SIGUSR2, dummy_sig_handler);
441
442
sigemptyset(&set);
443
sigaddset(&set, SIGCHLD);
444
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) == 0);
445
446
if (dequeue)
447
support_sysctlset("kern.wait_dequeue_sigchld", 1);
448
else
449
support_sysctlset("kern.wait_dequeue_sigchld", 0);
450
451
pid = fork();
452
ATF_REQUIRE(pid >= 0);
453
if (pid == 0) {
454
test_child();
455
exit(0);
456
}
457
458
bzero(&si, sizeof(si));
459
ATF_REQUIRE(waitid(P_PID, pid, &si, WSTOPPED) == 0);
460
461
support_check_siginfo(CLD_STOPPED, SIGSTOP, pid, &si, SIGCHLD);
462
support_check_sigchld(&set, CLD_STOPPED, SIGSTOP, pid, dequeue);
463
464
ATF_REQUIRE(kill(pid, SIGCONT) == 0);
465
466
bzero(&si, sizeof(si));
467
ATF_REQUIRE(waitid(P_PID, pid, &si, WCONTINUED) == 0);
468
469
support_check_siginfo(CLD_CONTINUED, SIGCONT, pid, &si, SIGCHLD);
470
support_check_sigchld(&set, CLD_CONTINUED, SIGCONT, pid, dequeue);
471
472
ATF_REQUIRE(kill(pid, SIGKILL) == 0);
473
474
bzero(&si, sizeof(si));
475
ATF_REQUIRE(waitid(P_PID, pid, &si, WEXITED) == 0);
476
477
support_check_siginfo(CLD_KILLED, SIGKILL, pid, &si, SIGCHLD);
478
}
479
480
ATF_TC_WITH_CLEANUP(test_sig_discard_ign_true);
481
ATF_TC_HEAD(test_sig_discard_ign_true, tc)
482
{
483
484
atf_tc_set_md_var(tc, "require.user", "root");
485
atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign on");
486
}
487
488
ATF_TC_BODY(test_sig_discard_ign_true, tc)
489
{
490
491
test_sig_discard_ign(true);
492
}
493
494
ATF_TC_CLEANUP(test_sig_discard_ign_true, tc)
495
{
496
497
support_sysctlset("kern.sig_discard_ign", 1);
498
}
499
500
ATF_TC_WITH_CLEANUP(test_sig_discard_ign_false);
501
ATF_TC_HEAD(test_sig_discard_ign_false, tc)
502
{
503
504
atf_tc_set_md_var(tc, "require.user", "root");
505
atf_tc_set_md_var(tc, "descr", "Test kern.sig_discard_ign off");
506
}
507
508
ATF_TC_BODY(test_sig_discard_ign_false, tc)
509
{
510
511
test_sig_discard_ign(false);
512
}
513
514
ATF_TC_CLEANUP(test_sig_discard_ign_false, tc)
515
{
516
517
support_sysctlset("kern.sig_discard_ign", 1);
518
}
519
520
ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_true);
521
ATF_TC_HEAD(test_wait_dequeue_sigchld_true, tc)
522
{
523
524
atf_tc_set_md_var(tc, "require.user", "root");
525
atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld on");
526
}
527
528
ATF_TC_BODY(test_wait_dequeue_sigchld_true, tc)
529
{
530
531
test_wait_dequeue_sigchld(true);
532
}
533
534
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_true, tc)
535
{
536
537
support_sysctlset("kern.wait_dequeue_sigchld", 1);
538
}
539
540
ATF_TC_WITH_CLEANUP(test_wait_dequeue_sigchld_false);
541
ATF_TC_HEAD(test_wait_dequeue_sigchld_false, tc)
542
{
543
544
atf_tc_set_md_var(tc, "require.user", "root");
545
atf_tc_set_md_var(tc, "descr", "Test kern.wait_dequeue_sigchld off");
546
}
547
548
ATF_TC_BODY(test_wait_dequeue_sigchld_false, tc)
549
{
550
551
test_wait_dequeue_sigchld(false);
552
}
553
554
ATF_TC_CLEANUP(test_wait_dequeue_sigchld_false, tc)
555
{
556
557
support_sysctlset("kern.wait_dequeue_sigchld", 1);
558
}
559
560
ATF_TP_ADD_TCS(tp)
561
{
562
563
ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain0);
564
ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain1);
565
ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain2);
566
ATF_TP_ADD_TC(tp, test_sigtimedwait_timeout_eagain3);
567
568
ATF_TP_ADD_TC(tp, test_sigtimedwait_large_timeout_eintr);
569
ATF_TP_ADD_TC(tp, test_sigtimedwait_infinity);
570
571
ATF_TP_ADD_TC(tp, test_sigtimedwait_einval);
572
573
ATF_TP_ADD_TC(tp, test_sigwait_eintr);
574
ATF_TP_ADD_TC(tp, test_sigwaitinfo_eintr);
575
576
ATF_TP_ADD_TC(tp, test_sig_discard_ign_true);
577
ATF_TP_ADD_TC(tp, test_sig_discard_ign_false);
578
579
ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_true);
580
ATF_TP_ADD_TC(tp, test_wait_dequeue_sigchld_false);
581
582
return (atf_no_error());
583
}
584
585