1 /* 2 * Copyright (c) Jiri Palecek<jpalecek (at) 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 "linux_syscall_numbers.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 */ 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 73 static void empty_handler(int sig) 74 { 75 } 76 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 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 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 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 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 128 static int my_rt_sigtimedwait(const sigset_t * set, siginfo_t * info, 129 struct timespec *timeout) 130 { 131 132 /* The last argument is (number_of_signals)/(bits_per_byte), which are 64 and 8, resp. */ 133 return ltp_syscall(__NR_rt_sigtimedwait, set, info, timeout, 8); 134 } 135 #endif 136 137 void test_empty_set(swi_func sigwaitinfo, int signo) 138 { 139 sigset_t sigs; 140 siginfo_t si; 141 pid_t child; 142 143 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 144 /* Run a child that will wake us up */ 145 child = create_sig_proc(100000, signo, UINT_MAX); 146 147 TEST(sigwaitinfo(&sigs, &si, NULL)); 148 REPORT_SUCCESS(-1, EINTR); 149 150 kill(child, SIGTERM); 151 } 152 153 void test_timeout(swi_func sigwaitinfo, int signo) 154 { 155 sigset_t sigs; 156 siginfo_t si; 157 pid_t child; 158 struct timespec ts = {.tv_sec = 1 }; 159 160 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 161 162 /* Run a child that will wake us up */ 163 child = create_sig_proc(100000, signo, UINT_MAX); 164 165 TEST(sigwaitinfo(&sigs, &si, &ts)); 166 REPORT_SUCCESS(-1, EAGAIN); 167 168 kill(child, SIGTERM); 169 } 170 171 /* Note: sigwait-ing for a signal that is not blocked is unspecified 172 * by POSIX; but works for non-ignored signals under Linux 173 */ 174 void test_unmasked_matching(swi_func sigwaitinfo, int signo) 175 { 176 sigset_t sigs; 177 siginfo_t si; 178 pid_t child; 179 180 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 181 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo); 182 183 /* Run a child that will wake us up */ 184 child = create_sig_proc(100000, signo, UINT_MAX); 185 186 TEST(sigwaitinfo(&sigs, &si, NULL)); 187 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child 188 && si.si_code == SI_USER 189 && si.si_signo == signo, "Struct siginfo mismatch"); 190 191 kill(child, SIGTERM); 192 } 193 194 void test_unmasked_matching_noinfo(swi_func sigwaitinfo, int signo) 195 { 196 sigset_t sigs; 197 pid_t child; 198 199 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 200 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo); 201 /* Run a child that will wake us up */ 202 child = create_sig_proc(100000, signo, UINT_MAX); 203 204 TEST(sigwaitinfo(&sigs, NULL, NULL)); 205 REPORT_SUCCESS(signo, 0); 206 207 kill(child, SIGTERM); 208 } 209 210 void test_masked_matching(swi_func sigwaitinfo, int signo) 211 { 212 sigset_t sigs, oldmask; 213 siginfo_t si; 214 pid_t child; 215 216 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 217 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo); 218 /* let's not get interrupted by our dying child */ 219 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD); 220 221 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs, 222 &oldmask); 223 224 /* don't wait on a SIGCHLD */ 225 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD); 226 227 /* Run a child that will wake us up */ 228 child = create_sig_proc(0, signo, 1); 229 230 TEST(sigwaitinfo(&sigs, &si, NULL)); 231 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child 232 && si.si_code == SI_USER 233 && si.si_signo == signo, "Struct siginfo mismatch"); 234 235 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed", 236 SIG_SETMASK, &oldmask, &oldmask); 237 238 tst_count--; 239 240 if (sigismember(&oldmask, signo)) 241 tst_resm(TPASS, "sigwaitinfo restored the original mask"); 242 else 243 tst_resm(TFAIL, 244 "sigwaitinfo failed to restore the original mask"); 245 } 246 247 void test_masked_matching_rt(swi_func sigwaitinfo, int signo) 248 { 249 sigset_t sigs, oldmask; 250 siginfo_t si; 251 pid_t child[2]; 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 TEST(sigwaitinfo(&sigs, &si, NULL)); 272 REPORT_SUCCESS_COND(signo, 0, si.si_pid == child[0] 273 && si.si_code == SI_USER 274 && si.si_signo == signo, "Struct siginfo mismatch"); 275 276 /* eat the other signal */ 277 tst_count--; 278 TEST(sigwaitinfo(&sigs, &si, NULL)); 279 REPORT_SUCCESS_COND(signo + 1, 0, si.si_pid == child[1] 280 && si.si_code == SI_USER 281 && si.si_signo == signo + 1, 282 "Struct siginfo mismatch"); 283 284 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed", 285 SIG_SETMASK, &oldmask, &oldmask); 286 287 tst_count--; 288 289 if (sigismember(&oldmask, signo)) 290 tst_resm(TPASS, "sigwaitinfo restored the original mask"); 291 else 292 tst_resm(TFAIL, 293 "sigwaitinfo failed to restore the original mask"); 294 } 295 296 void test_masked_matching_noinfo(swi_func sigwaitinfo, int signo) 297 { 298 sigset_t sigs, oldmask; 299 pid_t child; 300 301 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 302 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo); 303 /* let's not get interrupted by our dying child */ 304 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD); 305 306 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs, 307 &oldmask); 308 309 /* don't wait on a SIGCHLD */ 310 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD); 311 312 /* Run a child that will wake us up */ 313 child = create_sig_proc(0, signo, 1); 314 315 TEST(sigwaitinfo(&sigs, NULL, NULL)); 316 REPORT_SUCCESS(signo, 0); 317 318 SUCCEED_OR_DIE(sigprocmask, "restoring original signal mask failed", 319 SIG_SETMASK, &oldmask, &oldmask); 320 321 tst_count--; 322 323 if (sigismember(&oldmask, signo)) 324 tst_resm(TPASS, "sigwaitinfo restored the original mask"); 325 else 326 tst_resm(TFAIL, 327 "sigwaitinfo failed to restore the original mask"); 328 329 } 330 331 void test_bad_address(swi_func sigwaitinfo, int signo) 332 { 333 sigset_t sigs, oldmask; 334 pid_t child; 335 336 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 337 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, signo); 338 /* let's not get interrupted by our dying child */ 339 SUCCEED_OR_DIE(sigaddset, "sigaddset failed", &sigs, SIGCHLD); 340 341 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &sigs, 342 &oldmask); 343 344 /* don't wait on a SIGCHLD */ 345 SUCCEED_OR_DIE(sigdelset, "sigaddset failed", &sigs, SIGCHLD); 346 347 /* Run a child that will wake us up */ 348 child = create_sig_proc(0, signo, 1); 349 350 TEST(sigwaitinfo(&sigs, (void *)1, NULL)); 351 REPORT_SUCCESS(-1, EFAULT); 352 353 SUCCEED_OR_DIE(sigprocmask, "sigprocmask failed", SIG_SETMASK, &oldmask, 354 &oldmask); 355 356 kill(child, SIGTERM); 357 } 358 359 void test_bad_address2(swi_func sigwaitinfo, int signo) 360 { 361 TEST(sigwaitinfo((void *)1, NULL, NULL)); 362 REPORT_SUCCESS(-1, EFAULT); 363 } 364 365 void test_bad_address3(swi_func sigwaitinfo, int signo) 366 { 367 sigset_t sigs; 368 SUCCEED_OR_DIE(sigemptyset, "sigemptyset failed", &sigs); 369 370 TEST(sigwaitinfo(&sigs, NULL, (void *)1)); 371 REPORT_SUCCESS(-1, EFAULT); 372 } 373 374 struct test_desc { 375 test_func tf; 376 swi_func swi; 377 int signo; 378 } tests[] = { 379 #ifdef TEST_RT_SIGTIMEDWAIT 380 { 381 test_empty_set, my_rt_sigtimedwait, SIGUSR1}, { 382 test_unmasked_matching, my_rt_sigtimedwait, SIGUSR1}, { 383 test_masked_matching, my_rt_sigtimedwait, SIGUSR1}, { 384 test_unmasked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, { 385 test_masked_matching_noinfo, my_rt_sigtimedwait, SIGUSR1}, { 386 test_bad_address, my_rt_sigtimedwait, SIGUSR1}, { 387 test_bad_address2, my_rt_sigtimedwait, SIGUSR1}, { 388 test_bad_address3, my_rt_sigtimedwait, SIGUSR1}, { 389 test_timeout, my_rt_sigtimedwait, 0}, 390 /* Special cases */ 391 /* 1: sigwaitinfo does respond to ignored signal */ 392 { 393 test_masked_matching, my_rt_sigtimedwait, SIGUSR2}, 394 /* 2: An ignored signal doesn't cause sigwaitinfo to return EINTR */ 395 { 396 test_timeout, my_rt_sigtimedwait, SIGUSR2}, 397 /* 3: The handler is not called when the signal is waited for by sigwaitinfo */ 398 { 399 test_masked_matching, my_rt_sigtimedwait, SIGTERM}, 400 /* 4: Simultaneous realtime signals are delivered in the order of increasing signal number */ 401 { 402 test_masked_matching_rt, my_rt_sigtimedwait, -1}, 403 #endif 404 #if defined TEST_SIGWAIT 405 { 406 test_unmasked_matching_noinfo, my_sigwait, SIGUSR1}, { 407 test_masked_matching_noinfo, my_sigwait, SIGUSR1}, 408 #endif 409 #if defined TEST_SIGWAITINFO 410 { 411 test_empty_set, my_sigwaitinfo, SIGUSR1}, { 412 test_unmasked_matching, my_sigwaitinfo, SIGUSR1}, { 413 test_masked_matching, my_sigwaitinfo, SIGUSR1}, { 414 test_unmasked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, { 415 test_masked_matching_noinfo, my_sigwaitinfo, SIGUSR1}, { 416 test_bad_address, my_sigwaitinfo, SIGUSR1}, { 417 test_bad_address2, my_sigwaitinfo, SIGUSR1}, 418 #endif 419 #if defined TEST_SIGTIMEDWAIT 420 { 421 test_empty_set, my_sigtimedwait, SIGUSR1}, { 422 test_unmasked_matching, my_sigtimedwait, SIGUSR1}, { 423 test_masked_matching, my_sigtimedwait, SIGUSR1}, { 424 test_unmasked_matching_noinfo, my_sigtimedwait, SIGUSR1}, { 425 test_masked_matching_noinfo, my_sigtimedwait, SIGUSR1}, { 426 test_bad_address, my_sigtimedwait, SIGUSR1}, { 427 test_bad_address2, my_sigtimedwait, SIGUSR1}, { 428 test_bad_address3, my_sigtimedwait, SIGUSR1}, { 429 test_timeout, my_sigtimedwait, 0}, 430 #endif 431 }; 432 433 #if defined TEST_SIGWAITINFO 434 const char *TCID = "sigwaitinfo01"; 435 #elif defined TEST_RT_SIGTIMEDWAIT 436 const char *TCID = "rt_sigtimedwait01"; 437 #elif defined TEST_SIGTIMEDWAIT 438 const char *TCID = "sigtimedwait01"; 439 #elif defined TEST_SIGWAIT 440 const char *TCID = "sigwait01"; 441 #endif 442 443 int TST_TOTAL = ARRAY_SIZE(tests); 444 445 int main(int argc, char **argv) 446 { 447 unsigned i; 448 int lc; 449 450 tst_parse_opts(argc, argv, NULL, NULL); 451 452 setup(); 453 454 for (lc = 0; TEST_LOOPING(lc); ++lc) { 455 tst_count = 0; 456 457 for (i = 0; i < ARRAY_SIZE(tests); i++) { 458 alarm(10); /* arrange a 10 second timeout */ 459 tst_resm(TINFO, "%p, %d", tests[i].swi, tests[i].signo); 460 tests[i].tf(tests[i].swi, tests[i].signo); 461 } 462 alarm(0); 463 } 464 465 cleanup(); 466 tst_exit(); 467 } 468