/** * @file * Tests if sigsuspend(2) correctly returns for an already-pending * blocked signal. * @legal * Copyright © 2004 <slamb@slamb.org>. * This file is part of sigsafe, which is released under the MIT license. * @version $Id$ * @author Scott Lamb <slamb@slamb.org> */ #include #include #include #include #include #include #include #include int error_wrap(int retval, const char *funcname) { if (retval < 0) { fprintf(stderr, "%s returned %d (errno==%d) (%s)\n", funcname, retval, errno, strerror(errno)); abort(); } return retval; } volatile sig_atomic_t sigusr1_received, sigalrm_received; void sigusr1_handler(int signum) { sigusr1_received = 1; } void sigalrm_handler(int signum) { sigalrm_received = 1; } int main(void) { sigset_t empty; struct sigaction sa; sigset_t pending; int retval; /* Handle and block signals */ error_wrap(sigemptyset(&sa.sa_mask), "sigemptyset"); error_wrap(sigaddset(&sa.sa_mask, SIGUSR1), "sigaddset"); error_wrap(sigaddset(&sa.sa_mask, SIGALRM), "sigaddset"); sa.sa_flags = 0; sa.sa_handler = &sigusr1_handler; error_wrap(sigaction(SIGUSR1, &sa, NULL), "sigaction"); sa.sa_handler = &sigalrm_handler; error_wrap(sigaction(SIGALRM, &sa, NULL), "sigaction"); error_wrap(sigprocmask(SIG_BLOCK, &sa.sa_mask, NULL), "sigprocmask"); /* Generate a SIGUSR1 immediately. */ raise(SIGUSR1); /* Generate a SIGALRM after about a second. */ alarm(1); error_wrap(sigpending(&pending), "sigpending"); assert( sigismember(&pending, SIGUSR1)); assert(!sigismember(&pending, SIGALRM)); error_wrap(sigemptyset(&empty), "sigemptyset"); retval = sigsuspend(&empty); if (sigusr1_received && !sigalrm_received) { printf("Received the SIGUSR1 first; good.\n"); return 0; } else if (sigalrm_received) { printf("Pending SIGUSR1 was discarded; bad.\n"); } else { printf("Received both signals? weird.\n"); } return 1; }