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 "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*/ 42static 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 71static void cleanup(void); 72 73static void empty_handler(int sig) 74{ 75} 76 77static 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 87static void cleanup(void) 88{ 89} 90 91typedef int (*swi_func) (const sigset_t * set, siginfo_t * info, 92 struct timespec * timeout); 93typedef void (*test_func) (swi_func, int); 94 95#ifdef TEST_SIGWAIT 96static 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 110static 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 119static 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 128static 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 137void 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 153void 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 */ 174void 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 194void 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 210void 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 247void 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 296void 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 331void 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 359void test_bad_address2(swi_func sigwaitinfo, int signo) 360{ 361 TEST(sigwaitinfo((void *)1, NULL, NULL)); 362 REPORT_SUCCESS(-1, EFAULT); 363} 364 365void 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 374struct 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 434const char *TCID = "sigwaitinfo01"; 435#elif defined TEST_RT_SIGTIMEDWAIT 436const char *TCID = "rt_sigtimedwait01"; 437#elif defined TEST_SIGTIMEDWAIT 438const char *TCID = "sigtimedwait01"; 439#elif defined TEST_SIGWAIT 440const char *TCID = "sigwait01"; 441#endif 442 443int TST_TOTAL = ARRAY_SIZE(tests); 444 445int 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