sigsetjmp -- Save Stack Environment and Signal Mask

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.

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 filesn",
                 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


Copyright (c) 1998 SAS Institute Inc. Cary, NC, USA. All rights reserved.