/**
* @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;
}