1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009 */
3
4 #define TST_NO_DEFAULT_MAIN
5 #include <errno.h>
6 #include <stdlib.h>
7 #include <limits.h>
8 #include "lapi/syscalls.h"
9 #include "libsigwait.h"
10 #include "tst_sig_proc.h"
11
test_empty_set(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)12 void test_empty_set(swi_func sigwaitinfo, int signo,
13 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
14 {
15 sigset_t sigs;
16 siginfo_t si;
17 pid_t child;
18
19 SAFE_SIGEMPTYSET(&sigs);
20
21 /* Run a child that will wake us up */
22 child = create_sig_proc(signo, INT_MAX, 100000);
23
24 TEST(sigwaitinfo(&sigs, &si, NULL));
25 if (TST_RET == -1) {
26 if (TST_ERR == EINTR)
27 tst_res(TPASS, "Wait interrupted by expected signal");
28 else
29 tst_res(TFAIL | TTERRNO, "Expected error number EINTR, got");
30 } else {
31 tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
32 }
33
34 SAFE_KILL(child, SIGTERM);
35 SAFE_WAIT(NULL);
36 }
37
test_timeout(swi_func sigwaitinfo,int signo,enum tst_ts_type type)38 void test_timeout(swi_func sigwaitinfo, int signo, enum tst_ts_type type)
39 {
40 sigset_t sigs;
41 siginfo_t si;
42 pid_t child;
43 struct tst_ts ts;
44
45 ts.type = type;
46 tst_ts_set_sec(&ts, 1);
47 tst_ts_set_nsec(&ts, 0);
48
49 SAFE_SIGEMPTYSET(&sigs);
50
51 /* Run a child that will wake us up */
52 child = create_sig_proc(signo, INT_MAX, 100000);
53
54 TEST(sigwaitinfo(&sigs, &si, tst_ts_get(&ts)));
55 if (TST_RET == -1) {
56 if (TST_ERR == EAGAIN)
57 tst_res(TPASS, "Wait interrupted by timeout");
58 else
59 tst_res(TFAIL | TTERRNO, "Expected error number EAGAIN, got");
60 } else {
61 tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
62 }
63
64 SAFE_KILL(child, SIGTERM);
65 SAFE_WAIT(NULL);
66 }
67
68 /* Note: sigwait-ing for a signal that is not blocked is unspecified
69 * by POSIX; but works for non-ignored signals under Linux
70 */
test_unmasked_matching(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)71 void test_unmasked_matching(swi_func sigwaitinfo, int signo,
72 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
73 {
74 sigset_t sigs;
75 siginfo_t si;
76 pid_t child;
77
78 SAFE_SIGEMPTYSET(&sigs);
79 SAFE_SIGADDSET(&sigs, signo);
80
81 /* Run a child that will wake us up */
82 child = create_sig_proc(signo, INT_MAX, 100000);
83
84 TEST(sigwaitinfo(&sigs, &si, NULL));
85 if (TST_RET == signo) {
86 if (si.si_pid == child && si.si_code == SI_USER &&
87 si.si_signo == signo)
88 tst_res(TPASS, "struct siginfo is correct");
89 else
90 tst_res(TFAIL, "struct siginfo mismatch");
91 } else {
92 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
93 }
94
95 SAFE_KILL(child, SIGTERM);
96 SAFE_WAIT(NULL);
97 }
98
test_unmasked_matching_noinfo(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)99 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo,
100 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
101 {
102 sigset_t sigs;
103 pid_t child;
104
105 SAFE_SIGEMPTYSET(&sigs);
106 SAFE_SIGADDSET(&sigs, signo);
107
108 /* Run a child that will wake us up */
109 child = create_sig_proc(signo, INT_MAX, 100000);
110
111 TEST(sigwaitinfo(&sigs, NULL, NULL));
112 if (TST_RET == signo)
113 tst_res(TPASS, "Wait interrupted by expected signal");
114 else
115 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
116
117 SAFE_KILL(child, SIGTERM);
118 SAFE_WAIT(NULL);
119 }
120
test_masked_matching(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)121 void test_masked_matching(swi_func sigwaitinfo, int signo,
122 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
123 {
124 sigset_t sigs, oldmask;
125 siginfo_t si;
126 pid_t child;
127
128 SAFE_SIGEMPTYSET(&sigs);
129 SAFE_SIGADDSET(&sigs, signo);
130
131 /* let's not get interrupted by our dying child */
132 SAFE_SIGADDSET(&sigs, SIGCHLD);
133
134 TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
135 if (TST_RET == -1)
136 tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
137
138 /* don't wait on a SIGCHLD */
139 SAFE_SIGDELSET(&sigs, SIGCHLD);
140
141 /* Run a child that will wake us up */
142 child = create_sig_proc(signo, 1, 0);
143
144 TEST(sigwaitinfo(&sigs, &si, NULL));
145 if (TST_RET == signo) {
146 if (si.si_pid == child && si.si_code == SI_USER &&
147 si.si_signo == signo)
148 tst_res(TPASS, "struct siginfo is correct");
149 else
150 tst_res(TFAIL, "struct siginfo mismatch");
151 } else {
152 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
153 }
154
155 TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
156 if (TST_RET == -1)
157 tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
158
159 if (sigismember(&sigs, signo))
160 tst_res(TPASS, "sigwaitinfo restored the original mask");
161 else
162 tst_res(TFAIL,
163 "sigwaitinfo failed to restore the original mask");
164
165 SAFE_KILL(child, SIGTERM);
166 SAFE_WAIT(NULL);
167 }
168
test_masked_matching_rt(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)169 void test_masked_matching_rt(swi_func sigwaitinfo, int signo,
170 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
171 {
172 sigset_t sigs, oldmask;
173 siginfo_t si;
174 pid_t child[2];
175 int status;
176
177 signo = SIGRTMIN + 1;
178
179 SAFE_SIGEMPTYSET(&sigs);
180 SAFE_SIGADDSET(&sigs, signo);
181 SAFE_SIGADDSET(&sigs, signo + 1);
182
183 /* let's not get interrupted by our dying child */
184 SAFE_SIGADDSET(&sigs, SIGCHLD);
185
186 TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
187 if (TST_RET == -1)
188 tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
189
190 /* don't wait on a SIGCHLD */
191 SAFE_SIGDELSET(&sigs, SIGCHLD);
192
193 /* Run a child that will wake us up */
194 child[0] = create_sig_proc(signo, 1, 0);
195 child[1] = create_sig_proc(signo + 1, 1, 0);
196
197 /* Ensure that the signals have been sent */
198 SAFE_WAITPID(child[0], &status, 0);
199 SAFE_WAITPID(child[1], &status, 0);
200
201 TEST(sigwaitinfo(&sigs, &si, NULL));
202 if (TST_RET == signo) {
203 if (si.si_pid == child[0] && si.si_code == SI_USER &&
204 si.si_signo == signo)
205 tst_res(TPASS, "struct siginfo is correct");
206 else
207 tst_res(TFAIL, "struct siginfo mismatch");
208 } else {
209 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
210 }
211
212 /* eat the other signal */
213 TEST(sigwaitinfo(&sigs, &si, NULL));
214 if (TST_RET == signo + 1) {
215 if (si.si_pid == child[1] && si.si_code == SI_USER &&
216 si.si_signo == signo + 1)
217 tst_res(TPASS, "struct siginfo is correct");
218 else
219 tst_res(TFAIL, "struct siginfo mismatch");
220 } else {
221 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
222 }
223
224 TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
225 if (TST_RET == -1)
226 tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
227
228 if (sigismember(&sigs, signo))
229 tst_res(TPASS, "sigwaitinfo restored the original mask");
230 else
231 tst_res(TFAIL,
232 "sigwaitinfo failed to restore the original mask");
233 }
234
test_masked_matching_noinfo(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)235 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo,
236 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
237 {
238 sigset_t sigs, oldmask;
239 pid_t child;
240
241 SAFE_SIGEMPTYSET(&sigs);
242 SAFE_SIGADDSET(&sigs, signo);
243
244 /* let's not get interrupted by our dying child */
245 SAFE_SIGADDSET(&sigs, SIGCHLD);
246
247 TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
248 if (TST_RET == -1)
249 tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
250
251 /* don't wait on a SIGCHLD */
252 SAFE_SIGDELSET(&sigs, SIGCHLD);
253
254 /* Run a child that will wake us up */
255 child = create_sig_proc(signo, 1, 0);
256
257 TEST(sigwaitinfo(&sigs, NULL, NULL));
258 if (TST_RET == signo)
259 tst_res(TPASS, "Wait interrupted by expected signal");
260 else
261 tst_res(TFAIL | TTERRNO, "sigwaitinfo() failed");
262
263 TEST(sigprocmask(SIG_SETMASK, &oldmask, &sigs));
264 if (TST_RET == -1)
265 tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
266
267 if (sigismember(&sigs, signo))
268 tst_res(TPASS, "sigwaitinfo restored the original mask");
269 else
270 tst_res(TFAIL,
271 "sigwaitinfo failed to restore the original mask");
272
273 SAFE_KILL(child, SIGTERM);
274 SAFE_WAIT(NULL);
275 }
276
test_bad_address(swi_func sigwaitinfo,int signo,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)277 void test_bad_address(swi_func sigwaitinfo, int signo,
278 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
279 {
280 sigset_t sigs, oldmask;
281 pid_t child;
282
283 SAFE_SIGEMPTYSET(&sigs);
284 SAFE_SIGADDSET(&sigs, signo);
285
286 /* let's not get interrupted by our dying child */
287 SAFE_SIGADDSET(&sigs, SIGCHLD);
288
289 TEST(sigprocmask(SIG_SETMASK, &sigs, &oldmask));
290 if (TST_RET == -1)
291 tst_brk(TBROK | TTERRNO, "sigprocmask() failed");
292
293 /* don't wait on a SIGCHLD */
294 SAFE_SIGDELSET(&sigs, SIGCHLD);
295
296 /* Run a child that will wake us up */
297 child = create_sig_proc(signo, 1, 0);
298
299 TEST(sigwaitinfo(&sigs, (void *)1, NULL));
300 if (TST_RET == -1) {
301 if (TST_ERR == EFAULT)
302 tst_res(TPASS, "Fault occurred while accessing the buffers");
303 else
304 tst_res(TFAIL | TTERRNO, "Expected error number EFAULT, got");
305 } else {
306 tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
307 }
308
309 TEST(sigprocmask(SIG_SETMASK, &oldmask, NULL));
310 if (TST_RET == -1)
311 tst_brk(TBROK | TTERRNO, "restoring original signal mask failed");
312
313 SAFE_KILL(child, SIGTERM);
314 SAFE_WAIT(NULL);
315 }
316
test_bad_address2(swi_func sigwaitinfo,int signo LTP_ATTRIBUTE_UNUSED,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)317 void test_bad_address2(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED,
318 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
319 {
320 pid_t pid;
321 int status;
322
323 pid = SAFE_FORK();
324 if (pid == 0) {
325 signal(SIGSEGV, SIG_DFL);
326
327 /*
328 * depending on glibc implementation we should
329 * either crash or get EFAULT
330 */
331 TEST(sigwaitinfo((void *)1, NULL, NULL));
332
333 if (TST_RET == -1 && TST_ERR == EFAULT)
334 _exit(0);
335
336 tst_res(TINFO | TTERRNO, "swi_func returned: %ld", TST_RET);
337 _exit(1);
338 }
339
340 SAFE_WAITPID(pid, &status, 0);
341
342 if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
343 || (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
344 tst_res(TPASS, "Child exited with expected code");
345 return;
346 }
347
348 if (WIFEXITED(status)) {
349 tst_res(TFAIL, "Unrecognised child exit code: %d",
350 WEXITSTATUS(status));
351 }
352 if (WIFSIGNALED(status)) {
353 tst_res(TFAIL, "Unrecognised child termsig: %d",
354 WTERMSIG(status));
355 }
356 }
357
test_bad_address3(swi_func sigwaitinfo,int signo LTP_ATTRIBUTE_UNUSED,enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)358 void test_bad_address3(swi_func sigwaitinfo, int signo LTP_ATTRIBUTE_UNUSED,
359 enum tst_ts_type type LTP_ATTRIBUTE_UNUSED)
360 {
361 sigset_t sigs;
362
363 SAFE_SIGEMPTYSET(&sigs);
364 TEST(sigwaitinfo(&sigs, NULL, (void *)1));
365 if (TST_RET == -1) {
366 if (TST_ERR == EFAULT)
367 tst_res(TPASS, "Fault occurred while accessing the buffers");
368 else
369 tst_res(TFAIL | TTERRNO, "Expected error number EFAULT, got");
370 } else {
371 tst_res(TFAIL, "Expected return value -1, got: %ld", TST_RET);
372 }
373 }
374
empty_handler(int sig LTP_ATTRIBUTE_UNUSED)375 static void empty_handler(int sig LTP_ATTRIBUTE_UNUSED)
376 {
377 }
378
sigwait_setup(void)379 void sigwait_setup(void)
380 {
381 signal(SIGUSR1, empty_handler);
382 signal(SIGALRM, empty_handler);
383 signal(SIGUSR2, SIG_IGN);
384 }
385