/** * @file * Tests if signals generated by alarm(2) are correctly held for * delivery if generated while the process is blocking SIGALRM. * SUSv3's Signal * Generation and Delivery section says that: *
* If the action associated with a blocked signal is anything other than to * ignore the signal, and if that signal is generated for the thread, the * signal shall remain pending until it is unblocked, it is accepted when it * is selected and returned by a call to the sigwait() function, or the action * associated with it is set to ignore the 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 sigalrm_received; void note_sigalrm (int signum) { sigalrm_received = 1; } int main(void) { sigset_t alrm_set, pending_set; struct timespec ts; int retval; /* Handle SIGALRM */ signal(SIGALRM, ¬e_sigalrm); /* Block SIGALRM */ error_wrap(sigemptyset(&alrm_set), "sigemptyset"); error_wrap(sigaddset(&alrm_set, SIGALRM), "sigaddset"); error_wrap(sigprocmask(SIG_BLOCK, &alrm_set, NULL), "sigprocmask"); /* Generate a SIGALRM after about a second. */ alarm(1); /* Wait for the alarm to be generated, giving plenty of leeway. */ ts.tv_sec = 2; ts.tv_nsec = 0; while ((retval = nanosleep(&ts, &ts)) == -1 && errno == EINTR) ; error_wrap(retval, "nanosleep"); error_wrap(sigpending(&pending_set), "sigpending"); if (sigismember(&pending_set, SIGALRM)) { printf("SIGALRM pending; good.\n"); } else { printf("SIGALRM not pending?!?\n"); return 1; } /* * Unblock the signal, allowing delivery. SUSv3 says: * * If there are any pending unblocked signals after the call to * sigprocmask(), at least one of those signals shall be delivered * before the call to sigprocmask() returns. * * Thus in the absence of other signals, sigalrm_received should be set * after this line. */ error_wrap(sigprocmask(SIG_UNBLOCK, &alrm_set, NULL), "sigprocmask"); if (sigalrm_received) { printf("SIGALRM received; good.\n"); return 0; } else { printf("SIGALRM was lost.\n"); return 1; } return 0; }