1 /*
2 * Copyright (c) Jiri Palecek<jpalecek@web.de>, 2009
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23 #include "test.h"
24 #include <errno.h>
25 #include <signal.h>
26 #include "../utils/include_j_h.h"
27 #include "../utils/common_j_h.c"
28 #include <limits.h>
29 #include "lapi/syscalls.h"
30
31 #define SUCCEED_OR_DIE(syscall, message, ...) \
32 (errno = 0, \
33 ({int ret=syscall(__VA_ARGS__); \
34 if (ret==-1) \
35 tst_brkm(TBROK|TERRNO, cleanup, message);\
36 ret;}))
37
38 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
39 exp_return and exp_errno, resp., and cond is true. If cond is not
40 true, report condition_errmsg
41 */
report_success_cond(const char * func,const char * file,int line,long exp_return,int exp_errno,int condition,char * condition_errmsg)42 static void report_success_cond(const char *func, const char *file, int line,
43 long exp_return, int exp_errno, int condition,
44 char *condition_errmsg)
45 {
46 if (exp_return == TEST_RETURN
47 && (exp_return != -1 || exp_errno == TEST_ERRNO))
48 if (condition)
49 tst_resm(TPASS, "Test passed");
50 else
51 tst_resm(TFAIL, "%s (%s: %d): %s", func, file, line,
52 condition_errmsg);
53 else if (TEST_RETURN != -1)
54 tst_resm(TFAIL,
55 "%s (%s: %d): Unexpected return value; expected %ld, got %ld",
56 func, file, line, exp_return, TEST_RETURN);
57 else
58 tst_resm(TFAIL | TTERRNO, "%s (%s: %d): Unexpected failure",
59 func, file, line);
60 }
61
62 #define REPORT_SUCCESS_COND(exp_return, exp_errno, condition, condition_errmsg) \
63 report_success_cond(__FUNCTION__, __FILE__, __LINE__, exp_return, exp_errno, condition, condition_errmsg);
64
65 /* Report success iff TEST_RETURN and TEST_ERRNO are equal to
66 exp_return and exp_errno, resp.
67 */
68 #define REPORT_SUCCESS(exp_return, exp_errno) \
69 REPORT_SUCCESS_COND(exp_return, exp_errno, 1, "");
70
71 static void cleanup(void);
72
empty_handler(int sig)73 static void empty_handler(int sig)
74 {
75 }
76
setup(void)77 static void setup(void)
78 {
79 tst_sig(FORK, DEF_HANDLER, cleanup);
80 signal(SIGUSR1, empty_handler);
81 signal(SIGALRM, empty_handler);
82 signal(SIGUSR2, SIG_IGN);
83
84 TEST_PAUSE;
85 }
86
cleanup(void)87 static void cleanup(void)
88 {
89 }
90
91 typedef int (*swi_func) (const sigset_t * set, siginfo_t * info,
92 struct timespec * timeout);
93 typedef void (*test_func) (swi_func, int);
94
95 #ifdef TEST_SIGWAIT
my_sigwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)96 static int my_sigwait(const sigset_t * set, siginfo_t * info,
97 struct timespec *timeout)
98 {
99 int ret;
100 int err = sigwait(set, &ret);
101
102 if (err == 0)
103 return ret;
104 errno = err;
105 return -1;
106 }
107 #endif
108
109 #ifdef TEST_SIGWAITINFO
my_sigwaitinfo(const sigset_t * set,siginfo_t * info,struct timespec * timeout)110 static int my_sigwaitinfo(const sigset_t * set, siginfo_t * info,
111 struct timespec *timeout)
112 {
113
114 return sigwaitinfo(set, info);
115 }
116 #endif
117
118 #ifdef TEST_SIGTIMEDWAIT
my_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)119 static int my_sigtimedwait(const sigset_t * set, siginfo_t * info,
120 struct timespec *timeout)
121 {
122
123 return sigtimedwait(set, info, timeout);
124 }
125 #endif
126
127 #ifdef TEST_RT_SIGTIMEDWAIT
my_rt_sigtimedwait(const sigset_t * set,siginfo_t * info,struct timespec * timeout)128 static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info,
129 struct timespec *timeout)
130 {
131 /* _NSIG is always the right number of bits of signal map for all arches */
132 return ltp_syscall(__NR_rt_sigtimedwait, set, info, timeout, _NSIG/8);
133 }
134 #endif
135
test_empty_set(swi_func sigwaitinfo,int signo)136 void test_empty_set(swi_func sigwaitinfo, int signo)
137 {
138 sigset_t sigs;
139 siginfo_t si;
140 pid_t child;
141
142 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
143 /* Run a child that will wake us up */
144 child = create_sig_proc(100000, signo, UINT_MAX);
145
146 TEST(sigwaitinfo(&sigs, &si, NULL));
147 REPORT_SUCCESS(-1, EINTR);
148
149 kill(child, SIGTERM);
150 }
151
test_timeout(swi_func sigwaitinfo,int signo)152 void test_timeout(swi_func sigwaitinfo, int signo)
153 {
154 sigset_t sigs;
155 siginfo_t si;
156 pid_t child;
157 struct timespec ts = {.tv_sec = 1 };
158
159 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
160
161 /* Run a child that will wake us up */
162 child = create_sig_proc(100000, signo, UINT_MAX);
163
164 TEST(sigwaitinfo(&sigs, &si, &ts));
165 REPORT_SUCCESS(-1, EAGAIN);
166
167 kill(child, SIGTERM);
168 }
169
170 /* Note: sigwait-ing for a signal that is not blocked is unspecified
171 * by POSIX; but works for non-ignored signals under Linux
172 */
test_unmasked_matching(swi_func sigwaitinfo,int signo)173 void test_unmasked_matching(swi_func sigwaitinfo, int signo)
174 {
175 sigset_t sigs;
176 siginfo_t si;
177 pid_t child;
178
179 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
180 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
181
182 /* Run a child that will wake us up */
183 child = create_sig_proc(100000, signo, UINT_MAX);
184
185 TEST(sigwaitinfo(&sigs, &si, NULL));
186 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
187 && si.si_code == SI_USER
188 && si.si_signo == signo, "Struct siginfo mismatch");
189
190 kill(child, SIGTERM);
191 }
192
test_unmasked_matching_noinfo(swi_func sigwaitinfo,int signo)193 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo)
194 {
195 sigset_t sigs;
196 pid_t child;
197
198 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
199 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
200 /* Run a child that will wake us up */
201 child = create_sig_proc(100000, signo, UINT_MAX);
202
203 TEST(sigwaitinfo(&sigs, NULL, NULL));
204 REPORT_SUCCESS(signo, 0);
205
206 kill(child, SIGTERM);
207 }
208
test_masked_matching(swi_func sigwaitinfo,int signo)209 void test_masked_matching(swi_func sigwaitinfo, int signo)
210 {
211 sigset_t sigs, oldmask;
212 siginfo_t si;
213 pid_t child;
214
215 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
216 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
217 /* let's not get interrupted by our dying child */
218 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
219
220 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
221 &oldmask);
222
223 /* don't wait on a SIGCHLD */
224 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
225
226 /* Run a child that will wake us up */
227 child = create_sig_proc(0, signo, 1);
228
229 TEST(sigwaitinfo(&sigs, &si, NULL));
230 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child
231 && si.si_code == SI_USER
232 && si.si_signo == signo, "Struct siginfo mismatch");
233
234 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
235 SIG_SETMASK, &oldmask, &oldmask);
236
237 tst_count--;
238
239 if (sigismember(&oldmask, signo))
240 tst_resm(TPASS, "sigwaitinfo restored the original mask");
241 else
242 tst_resm(TFAIL,
243 "sigwaitinfo failed to restore the original mask");
244 }
245
test_masked_matching_rt(swi_func sigwaitinfo,int signo)246 void test_masked_matching_rt(swi_func sigwaitinfo, int signo)
247 {
248 sigset_t sigs, oldmask;
249 siginfo_t si;
250 pid_t child[2];
251 int status;
252
253 signo = SIGRTMIN + 1;
254
255 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
256 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
257 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo + 1);
258 /* let's not get interrupted by our dying child */
259 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
260
261 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
262 &oldmask);
263
264 /* don't wait on a SIGCHLD */
265 SUCCEED_OR_DIE(sigdelset, "sigdelset failed", &sigs, SIGCHLD);
266
267 /* Run a child that will wake us up */
268 child[0] = create_sig_proc(0, signo, 1);
269 child[1] = create_sig_proc(0, signo + 1, 1);
270
271 /* Ensure that the signals have been sent */
272 waitpid(child[0], &status, 0);
273 waitpid(child[1], &status, 0);
274
275 TEST(sigwaitinfo(&sigs, &si, NULL));
276 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0]
277 && si.si_code == SI_USER
278 && si.si_signo == signo, "Struct siginfo mismatch");
279
280 /* eat the other signal */
281 tst_count--;
282 TEST(sigwaitinfo(&sigs, &si, NULL));
283 REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1]
284 && si.si_code == SI_USER
285 && si.si_signo == signo + 1,
286 "Struct siginfo mismatch");
287
288 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
289 SIG_SETMASK, &oldmask, &oldmask);
290
291 tst_count--;
292
293 if (sigismember(&oldmask, signo))
294 tst_resm(TPASS, "sigwaitinfo restored the original mask");
295 else
296 tst_resm(TFAIL,
297 "sigwaitinfo failed to restore the original mask");
298 }
299
test_masked_matching_noinfo(swi_func sigwaitinfo,int signo)300 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo)
301 {
302 sigset_t sigs, oldmask;
303 pid_t child;
304
305 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
306 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
307 /* let's not get interrupted by our dying child */
308 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
309
310 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
311 &oldmask);
312
313 /* don't wait on a SIGCHLD */
314 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
315
316 /* Run a child that will wake us up */
317 child = create_sig_proc(0, signo, 1);
318
319 TEST(sigwaitinfo(&sigs, NULL, NULL));
320 REPORT_SUCCESS(signo, 0);
321
322 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed",
323 SIG_SETMASK, &oldmask, &oldmask);
324
325 tst_count--;
326
327 if (sigismember(&oldmask, signo))
328 tst_resm(TPASS, "sigwaitinfo restored the original mask");
329 else
330 tst_resm(TFAIL,
331 "sigwaitinfo failed to restore the original mask");
332
333 }
334
test_bad_address(swi_func sigwaitinfo,int signo)335 void test_bad_address(swi_func sigwaitinfo, int signo)
336 {
337 sigset_t sigs, oldmask;
338 pid_t child;
339
340 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
341 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo);
342 /* let's not get interrupted by our dying child */
343 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD);
344
345 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs,
346 &oldmask);
347
348 /* don't wait on a SIGCHLD */
349 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD);
350
351 /* Run a child that will wake us up */
352 child = create_sig_proc(0, signo, 1);
353
354 TEST(sigwaitinfo(&sigs, (void *)1, NULL));
355 REPORT_SUCCESS(-1, EFAULT);
356
357 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask,
358 &oldmask);
359
360 kill(child, SIGTERM);
361 }
362
test_bad_address2(swi_func sigwaitinfo,int signo)363 void test_bad_address2(swi_func sigwaitinfo, int signo)
364 {
365 pid_t pid;
366 int status;
367
368 switch (pid = fork()) {
369 case -1:
370 tst_brkm(TBROK | TERRNO, NULL, "fork() failed");
371 case 0:
372 signal(SIGSEGV, SIG_DFL);
373
374 /*
375 * depending on glibc implementation we should
376 * either crash or get EFAULT
377 */
378 TEST(sigwaitinfo((void *)1, NULL, NULL));
379
380 if (TEST_RETURN == -1 && TEST_ERRNO == EFAULT)
381 _exit(0);
382
383 tst_resm(TINFO | TTERRNO, "swi_func returned: %ld",
384 TEST_RETURN);
385 _exit(1);
386 break;
387 default:
388 break;
389 }
390
391 SUCCEED_OR_DIE(waitpid, "waitpid failed", pid, &status, 0);
392
393 if ((WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
394 || (WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
395 tst_resm(TPASS, "Test passed");
396 return;
397 }
398
399 if (WIFEXITED(status)) {
400 tst_resm(TFAIL, "Unrecognised child exit code: %d",
401 WEXITSTATUS(status));
402 }
403 if (WIFSIGNALED(status)) {
404 tst_resm(TFAIL, "Unrecognised child termsig: %d",
405 WTERMSIG(status));
406 }
407 }
408
test_bad_address3(swi_func sigwaitinfo,int signo)409 void test_bad_address3(swi_func sigwaitinfo, int signo)
410 {
411 sigset_t sigs;
412 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs);
413
414 TEST(sigwaitinfo(&sigs, NULL, (void *)1));
415 REPORT_SUCCESS(-1, EFAULT);
416 }
417
418 struct test_desc {
419 test_func tf;
420 swi_func swi;
421 int signo;
422 } tests[] = {
423 #ifdef TEST_RT_SIGTIMEDWAIT
424 {
425 test_empty_set, my_rt_sigtimedwait, SIGUSR1}, {
426 test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, {
427 test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, {
428 test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
429 test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, {
430 test_bad_address, my_rt_sigtimedwait, SIGUSR1}, {
431 test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, {
432 test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, {
433 test_timeout, my_rt_sigtimedwait, 0},
434 /* Special cases */
435 /* 1: sigwaitinfo does respond to ignored signal */
436 {
437 test_masked_matching, my_rt_sigtimedwait, SIGUSR2},
438 /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */
439 {
440 test_timeout, my_rt_sigtimedwait, SIGUSR2},
441 /* 3: The handler is not called when the signal is waited for by sigwaitinfo */
442 {
443 test_masked_matching, my_rt_sigtimedwait, SIGTERM},
444 /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */
445 #if !(defined(ANDROID) && !defined(__LP64__))
446 {
447 test_masked_matching_rt, my_rt_sigtimedwait, -1},
448 #endif
449 #endif
450 #if defined TEST_SIGWAIT
451 {
452 test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, {
453 test_masked_matching_noinfo, my_sigwait, SIGUSR1},
454 #endif
455 #if defined TEST_SIGWAITINFO
456 {
457 test_empty_set, my_sigwaitinfo, SIGUSR1}, {
458 test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, {
459 test_masked_matching, my_sigwaitinfo, SIGUSR1}, {
460 test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
461 test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, {
462 test_bad_address, my_sigwaitinfo, SIGUSR1}, {
463 test_bad_address2, my_sigwaitinfo, SIGUSR1},
464 #endif
465 #if defined TEST_SIGTIMEDWAIT
466 {
467 test_empty_set, my_sigtimedwait, SIGUSR1}, {
468 test_unmasked_matching, my_sigtimedwait, SIGUSR1}, {
469 test_masked_matching, my_sigtimedwait, SIGUSR1}, {
470 test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
471 test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, {
472 test_bad_address, my_sigtimedwait, SIGUSR1}, {
473 test_bad_address2, my_sigtimedwait, SIGUSR1}, {
474 test_bad_address3, my_sigtimedwait, SIGUSR1}, {
475 test_timeout, my_sigtimedwait, 0},
476 #endif
477 };
478
479 #if defined TEST_SIGWAITINFO
480 const char *TCID = "sigwaitinfo01";
481 #elif defined TEST_RT_SIGTIMEDWAIT
482 const char *TCID = "rt_sigtimedwait01";
483 #elif defined TEST_SIGTIMEDWAIT
484 const char *TCID = "sigtimedwait01";
485 #elif defined TEST_SIGWAIT
486 const char *TCID = "sigwait01";
487 #endif
488
489 int TST_TOTAL = ARRAY_SIZE(tests);
490
main(int argc,char ** argv)491 int main(int argc, char **argv)
492 {
493 unsigned i;
494 int lc;
495
496 tst_parse_opts(argc, argv, NULL, NULL);
497
498 setup();
499
500 for (lc = 0; TEST_LOOPING(lc); ++lc) {
501 tst_count = 0;
502
503 for (i = 0; i < ARRAY_SIZE(tests); i++) {
504 alarm(10); /* arrange a 10 second timeout */
505 tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo);
506 tests[i].tf(tests[i].swi, tests[i].signo);
507 }
508 alarm(0);
509 }
510
511 cleanup();
512 tst_exit();
513 }
514