Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

364 Signals Chapter 10


{
while (sigflag == 0)
sigsuspend(&zeromask); /* and wait for child */
sigflag = 0;
/* Reset signal mask to original value */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}

Figure 10.24Routines to allow a parent and child to synchronize

We use the two user-defined signals:SIGUSR1is sent by the parent to the child, and
SIGUSR2 is sent by the child to the parent. In Figure15.7, we show another
implementation of these five functions using pipes.

Thesigsuspendfunction is fine if we want to go to sleep while we’rewaiting for a
signal to occur (as we’ve shown in the previous two examples), but what if we want to
call other system functions while we’rewaiting? Unfortunately,this problem has no
bulletproof solution unless we use multiple threads and dedicate a separate thread to
handling signals, as we discuss in Section 12.8.
Without using threads, the best we can do is to set a global variable in the signal
handler when the signal occurs. For example, if we catch bothSIGINTandSIGALRM
and install the signal handlers using thesignal_intr function, the signals will
interrupt any slow system call that is blocked. The signals aremost likely to occur
when we’reblocked in a call to thereadfunction waiting for input from a slow device.
(This is especially true forSIGALRM,since we set the alarm clock to prevent us from
waiting forever for input.) The code to handle this looks similar to the following:
if (intr_flag) /* flag set by our SIGINT handler */
handle_intr();
if (alrm_flag) /* flag set by our SIGALRM handler */
handle_alrm();
/* signals occurring in here are lost */
while (read( ... ) < 0) {
if (errno == EINTR) {
if (alrm_flag)
handle_alrm();
else if (intr_flag)
handle_intr();
}else {
/* some other error */
}
}else if (n == 0) {
/* end of file */
}else {
/* process input */
}
Free download pdf