Advanced Programming in the UNIX® Environment

(lily) #1
ptg10805159

340 Signals Chapter 10


Earlier implementations ofsleeplooked like our program, with problems 1 and 2
corrected as described. Thereare two ways to correct problem 3. The first uses
setjmp,which we show in the next example. The other usessigprocmaskand
sigsuspend,and we describe it in Section 10.19.

Example


The SVR2 implementation ofsleepusedsetjmpandlongjmp(Section 7.10) to avoid
the race condition described in problem 3 of the previous example.Asimple version of
this function, calledsleep2, is shown in Figure10.8. (Toreduce the size of this
example, we don’t handle problems 1 and 2 described earlier.)
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>

static jmp_buf env_alrm;

static void
sig_alrm(int signo)
{
longjmp(env_alrm, 1);
}

unsigned int
sleep2(unsigned int seconds)
{
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
return(seconds);
if (setjmp(env_alrm) == 0) {
alarm(seconds); /* start the timer */
pause(); /* next caught signal wakes us up */
}
return(alarm(0)); /* turn off timer, return unslept time */
}

Figure 10.8Another (imperfect) implementation ofsleep

Thesleep2function avoids the race condition from Figure10.7. Even if thepauseis
never executed, thesleep2function returns when theSIGALRMoccurs.
Thereis, however,another subtle problem with thesleep2function that involves
its interaction with other signals. If theSIGALRMinterrupts some other signal handler,
then when we calllongjmp, we abort the other signal handler.Figure10.9 shows this
scenario. The loop in theSIGINThandler was written so that it executes for longer
than 5 seconds on one of the systems used by the author.Wesimply want it to execute
longer than the argument tosleep2.The integerkis declared asvolatileto prevent
an optimizing compiler from discarding the loop.
Free download pdf