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