Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

Section 10.15 sigsetjmpandsiglongjmpFunctions 357


{
time_t starttime;
if (canjump == 0)
return; /* unexpected signal, ignore */
pr_mask("starting sig_usr1: ");
alarm(3); /* SIGALRM in 3 seconds */
starttime = time(NULL);
for ( ; ; ) /* busy wait for 5 seconds */
if (time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: ");
canjump = 0;
siglongjmp(jmpbuf, 1); /* jump back to main, don’t return */
}
static void
sig_alrm(int signo)
{
pr_mask("in sig_alrm: ");
}

Figure 10.20Example of signal masks,sigsetjmp,andsiglongjmp

This program demonstrates another technique that should be used whenever
siglongjmpis called from a signal handler.Weset the variablecanjumpto a nonzero
value only after we’ve calledsigsetjmp.This variable is examined in the signal
handler,andsiglongjmpis called only if the flagcanjumpis nonzero. This technique
provides protection against the signal handler being called at some earlier or later time,
when the jump buffer hasn’t been initialized bysigsetjmp.(In this trivial program,
we terminate quickly after thesiglongjmp,but in larger programs, the signal handler
may remain installed long after thesiglongjmp.) Providing this type of protection
usually isn’t required withlongjmpin normal C code (as opposed to a signal handler).
Since a signal can occur atanytime, however, we need the added protection in a signal
handler.
Here, we use the data typesig_atomic_t,which is defined by the ISO C standard
to be the type of variable that can be written without being interrupted. By this we
mean that a variable of this type should not extend across page boundaries on a system
with virtual memory and can be accessed with a single machine instruction, for
example. Wealways include the ISO type qualifiervolatilefor these data types as
well, since the variable is being accessed by two different threads of control: themain
function and the asynchronously executing signal handler.Figure10.21 shows a
timeline for this program. Wecan divide Figure10.21 into three parts: the left part
(corresponding tomain), the center part (sig_usr1), and the right part (sig_alrm).
While the process is executing in the left part, its signal mask is 0 (no signals are
blocked). While executing in the center part, its signal mask is SIGUSR1.While
executing in the right part, its signal mask isSIGUSR1|SIGALRM.
Free download pdf