The Linux Programming Interface

(nextflipdebug5) #1

1368 Chapter 63


63.5 Waiting on Signals and File Descriptors


Sometimes, a process needs to simultaneously wait for I/O to become possible on
one of a set of file descriptors or for the delivery of a signal. We might attempt to
perform such an operation using select(), as shown in Listing 63-7.

Listing 63-7: Incorrect method of unblocking signals and calling select()

sig_atomic_t gotSig = 0;

void
handler(int sig)
{
gotSig = 1;
}

int
main(int argc, char *argv[])
{
struct sigaction sa;
...

sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
errExit("sigaction");

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

...
}

The problem with this code is that if the signal (SIGUSR1 in this example) arrives
after establishing the handler but before select() is called, then the select() call will
nevertheless block. (This is a form of race condition.) We now look at some solu-
tions to this problem.

Since version 2.6.27, Linux provides a further technique that can be used to
simultaneously wait on signals and file descriptors: the signalfd mechanism
described in Section 22.11. Using this mechanism, we can receive signals via a
Free download pdf