432 Chapter 21
Note that using #ifdef was the simplest way of writing the program in Listing 21-2
in a standards-conformant fashion. In particular, we could not have replaced the
#ifdef with the following run-time check:
if (useSiglongjmp)
s = sigsetjmp(senv, 1);
else
s = setjmp(env);
if (s == 0)
...
This is not permitted because SUSv3 doesn’t allow setjmp() and sigsetjmp() to be used
within an assignment statement (see Section 6.8).
Listing 21-2: Performing a nonlocal goto from a signal handler
––––––––––––––––––––––––––––––––––––––––––––––––––signals/sigmask_longjmp.c
#define _GNU_SOURCE /* Get strsignal() declaration from <string.h> */
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include "signal_functions.h" /* Declaration of printSigMask() */
#include "tlpi_hdr.h"
static volatile sig_atomic_t canJump = 0;
/* Set to 1 once "env" buffer has been
initialized by [sig]setjmp() */
#ifdef USE_SIGSETJMP
static sigjmp_buf senv;
#else
static jmp_buf env;
#endif
static void
handler(int sig)
{
/* UNSAFE: This handler uses non-async-signal-safe functions
(printf(), strsignal(), printSigMask(); see Section 21.1.2) */
printf("Received signal %d (%s), signal mask is:\n", sig,
strsignal(sig));
printSigMask(stdout, NULL);
if (!canJump) {
printf("'env' buffer not yet set, doing a simple return\n");
return;
}
#ifdef USE_SIGSETJMP
siglongjmp(senv, 1);
#else
longjmp(env, 1);
#endif
}