The pselect() call:
ready = pselect(nfds, &readfds, &writefds, NULL, timeout, &sigmask);
is equivalent to atomically performing the following steps:
sigset_t origmask;
sigprocmask(SIG_SETMASK, &sigmask, &origmask);
ready = select(nfds, &readfds, &writefds, NULL, timeout);
sigprocmask(SIG_SETMASK, &origmask, NULL); /* Restore signal mask */
pselect() is safe because signals in sigmask are only unblocked inside the system call.
pselect() allows us to safely wait for the signal:
sigset_t emptyset, blockset;
struct sigaction sa;
/* Block the signal */
sigemptyset(&blockset);
sigaddset(&blockset, SIGUSR1);
sigprocmask(SIG_BLOCK, &blockset, NULL);
/* Install handler */
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &sa, NULL);
/* Unblock signal; wait for ready fd or signal */
sigemptyset(&emptyset); /* Signal mask to use during pselect() */
ready = pselect(nfds, &readfds, NULL, NULL, NULL, &emptyset);
/* Remaining code as for select() */
if (ready > 0) {
printf("%d file descriptors ready\n", ready);
} else if (ready == -1 && errno == EINTR) {
if (gotSig)
printf("Got signal\n");
} else {
/* Some other error */
}
(C) 2006, Michael Kerrisk