ptg10805159
Section 10.16 sigsuspendFunction 359
10.16 sigsuspendFunction
We have seen how we can change the signal mask for a process to block and unblock
selected signals. We can use this technique to protect critical regions of code that we
don’t want interrupted by a signal. But what if we want to unblock a signal and then
pause,waiting for the previously blocked signal to occur? Assuming that the signal is
SIGINT,the incorrect way to do this is
sigset_t newmask, oldmask;
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
/* block SIGINT and save current signal mask */
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
/* critical region of code */
/* restore signal mask, which unblocks SIGINT */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
/* window is open */
pause(); /* wait for signal to occur */
/* continue processing */
If the signal is sent to the process while it is blocked, the signal delivery will be deferred
until the signal is unblocked. To the application, this can look as if the signal occurs
between the unblocking and thepause(depending on how the kernel implements
signals). If this happens, or if the signal does occur between the unblocking and the
pause, we have a problem. Any occurrence of the signal in this window of time is lost,
in the sense that we might not see the signal again, in which case thepausewill block
indefinitely.This is another problem with the earlier unreliable signals.
To correct this problem, we need a way to both restorethe signal mask and put the
process to sleep in a single atomic operation. This feature is provided by the
sigsuspendfunction.
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
Returns:−1witherrnoset toEINTR
The signal mask of the process is set to the value pointed to bysigmask.Then the
process is suspended until a signal is caught or until a signal occurs that terminates the
process. Ifasignal is caught and if the signal handler returns, then sigsuspend
returns, and the signal mask of the process is set to its value beforethe call to
sigsuspend.
Note that there is no successful return from this function. If it returns to the caller,it
always returns−1witherrnoset toEINTR(indicating an interrupted system call).