Problem: how to safely wait for a file descriptor or a signal?
The problem is that the following code has a race:
sig_atomic_t gotSig = 0; /* Global flag */
void
handler(int sig)
{
gotSig = 1; /* Tell main() we got a signal */
} /* handler */
int
main(int argc, char *argv[])
{
struct sigaction sa;
...
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &sa, NULL);
...
/* What if the signal is delivered now? */
ready = select(nfds, &readfds, NULL, NULL, NULL);
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 */
}
First signal might arrive before select(): if so, select() only returns after a second signal arrives.
Even blocking the signal (sigprocmask(2)) until just before the select() call does not eliminate the race.
(C) 2006, Michael Kerrisk