Chapter Contents

Previous

Next
sigsetjmp

sigsetjmp



Save Stack Environment and Signal Mask

Portability: POSIX.1 conforming


SYNOPSIS
DESCRIPTION
RETURN VALUE
IMPLEMENTATION
EXAMPLE
RELATED FUNCTIONS
SEE ALSO


SYNOPSIS

#include <lcjmp.h>

int sigsetjmp(sigjmp_buf env, int savemask);

The synopsis for the POSIX implementation is

#include <setjmp.h>

int sigsetjmp(sigjmp_buf env, int savemask);

You should use <setjmp.h> only if an appropriate feature test macro has been defined.


DESCRIPTION

sigsetjmp saves the current stack environment and signal mask. env is a pointer to the sigjmp_buf structure that contains the current environment. savemask specifies whether or not the signal mask is saved; if savemask is 0, the current signal mask is not saved. A nonzero value specifies that the current signal mask is saved.

See blkjmp for more information on saving the signal mask as a part of a setjmp operation and restoring it as part of a longjmp operation.


RETURN VALUE

sigsetjmp returns the value 0, or the value specified in the call to siglongjmp .


IMPLEMENTATION

sigsetjmp is defined as a macro and should not be used with #undef .


EXAMPLE

The following example is an outline of an application using sigsetjmp and siglongjmp for error recovery. The program is designed so that if a protection exception ( SIGSEGV ) occurs, control is returned using siglongjmp to any of several locations, depending on when the error occurred. The signal mask at the time of the exception may differ from the signal mask of the cleanup code, which is unknown.

   /* This example must be compiled with the posix           */
   /* compiler option.                                       */
#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>
#include <lclib.h>

   /* This is the address of a sigjmp buffer defining         */
   /* the SIGSEGV                                             */
   /*  recovery location.                                     */
sigjmp_buf *recover;
extern void reinit(void);
extern void fixfiles(void);
extern void int_handler(int);   /* SIGINT handler - not shown */
extern void alrm_handler(int);  /* SIGALRM handler - not shown*/
extern void term_handler(int);  /* SIGTERM handler - not shown*/
static void segv_handler(int);  /* SIGSEGV handler            */

   /* shutdown flag, set by SIGTERM handler */
int shutdown = 0;

main() {
   sigjmp_buf mainbuf;
   struct sigaction int_action, alrm_action, segv_action;
   sigset_t newmask, oldmask;

      /* This code defines the normal recovery action, which  */
      /* is to reinitialize the program.  No signals are      */
      /* masked at this  point.                               */                  */
   if (sigsetjmp(mainbuf, 1)) {   /* if a SIGSEGV occurred    */
      fputs("SIGSEGV error, reinitializing...", stderr);
      fflush(stderr);
      reinit();
   }
   recover = &mainbuf;            /* Save recovery buffer.    */

      /* Define signal actions.                               */
   segv_action.sa_handler = &segv_handler;
   segv_action.sa_flags = 0;
      /* Block SIGINT, SIGALRM and SIGTERM while we're        */
      /* handling SIGSEGV.                                    */
   sigemptyset(&segv_action.sa_mask);
   sigaddset(&segv_action.sa_mask, SIGINT);
   sigaddset(&segv_action.sa_mask, SIGALRM);
   sigaddset(&segv_action.sa_mask, SIGTERM);
   sigaction(SIGSEGV, &segv_action, NULL);

   alrm_action.sa_handler = &alrm_handler;
   alrm_action.sa_flags = 0;
      /* Block SIGINT while we're handling SIGALRM.           */
   sigemptyset(&alrm_action.sa_mask);
   sigaddset(&alrm_action.sa_mask, SIGINT);
   sigaction(SIGALRM, &alrm_action, NULL);

   int_action.sa_handler = &int_handler;
   int_action.sa_flags = 0;
      /* Block SIGALRM while we're handling SIGINT.           */
   sigemptyset(&int_action.sa_mask);
   sigaddset(&int_action.sa_mask, SIGALRM);
   sigaction(SIGINT, &int_action, NULL);

   term_action.sa_handler = &term_handler;
   term_action.sa_flags = 0;
      /* Only SIGTERM is blocked in the SIGTERM handler.            */
   sigemptyset(&term_action.sa_mask);
   sigaction(SIGTERM, &term_action, NULL);

   sigemptyset(&newmask); /* Set up mask to block SIGINT + SIGALRM. */
   sigaddset(&newmask, SIGINT);
   sigaddset(&newmask, SIGALRM);

   alarm(5);              /* Perform checkpoint every 5 seconds.    */

   while(!shutdown) {
      sigjmp_buf updbuf;  /* recovery buffer for update code        */
      sigjmp_buf *old_recover;   /* previous recovery buffer        */
         /* This part of the application reads input from stdin ... */
            .
            .
            .
         /* This part of the program updates a database and is      */
         /*  protected from SIGINT and SIGALRM interrupts.          */
      sigprocmask(SIG_BLOCK, &newmask, &oldmask); /* Block signals. */
      old_recover = recover; /* Save previous recovery information. */
      if (sigsetjmp(updbuf, 1)) {    /* error during update         */
         fputs("SIGSEGV during database update - fixing files\n",
               stderr);
         fixfiles();
         recover = old_recover;
         sigprocmask(SIG_SETMASK, &oldmask, 0);  /* Restore mask.   */
         continue;
      }
      recover = &updbuf;  /* Define new recovery point.             */
         .
         .                /* Update the database.                   */
         .
      recover = old_recover;   /* Restore old recovery point.       */
         /* Restore the mask.                                       */
      sigprocmask(SIG_SETMASK, &oldmask, NULL);
   }
}

static void segv_handler(int signum) {
      /* This routine handles SIGSEGV errors by escaping to the     */
      /*  cleanup routine identified by recover.  The handler has   */
      /*  SIGALRM, SIGINT and SIGTERM signals blocked.  The mask    */
      /*  to be used during recovery is unknown.                    */

   btrace(0);            /* Get traceback for diagnosis of problem. */
   siglongjmp(*recover, 1);   /* Escape to cleanup routine.         */
}


RELATED FUNCTIONS

setjmp , siglongjmp


SEE ALSO


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.