siglongjmp()--Perform Nonlocal Goto with Signal Handling


  Syntax
 #include <setjmp.h>

 void siglongjmp( sigjmp_buf env, int val );   

  Service Program Name: QPOSSRV1

  Default Public Authority: *USE

  Threadsafe: Yes

The siglongjmp() function restores the stack environment previously saved in env by sigsetjmp(). siglongjmp() also provides the option to restore the signal mask, depending on whether the signal mask was saved by sigsetjmp().

siglongjmp() is similar to longjmp(), except for the optional capability of restoring the signal mask.

The sigsetjmp() and siglongjmp() functions provide a way to perform a nonlocal "goto."

A call to sigsetjmp() causes the current stack environment (including, optionally, the signal mask) to be saved in env. A subsequent call to siglongjmp() does the following:

Processing resumes as if the sigsetjmp() call had just returned the given val. All variables, (except register variables) that are accessible to the function that receives control contain the values they had when siglongjmp() was called. The values of register variables are unpredictable. Nonvolatile auto variables that are changed between calls to sigsetjmp() and siglongjmp() are also unpredictable.

Note: When using siglongjmp(), the function in which the corresponding call to sigsetjmp() was made must not have returned first. Unpredictable program behavior occurs if siglongjmp() is called after the function calling sigsetjmp() has returned.

The val argument passed to siglongjmp() must be nonzero. If the val argument is equal to zero, siglongjmp() substitutes a 1 in its place.

siglongjmp() does not use the normal function call and return mechanisms. siglongjmp() restores the saved signal mask only if the env parameter was initialized by a call to sigsetjmp() with a nonzero savemask argument.


Authorities and Locks

None.


Parameters

env
(Input) An array type that holds the information needed to restore a calling environment.

val
(Input) The return value.

Return Value

None.


Error Conditions

The siglongjmp() function does not return an error.


Usage Notes

The sigsetjmp()-siglongjmp() pair and the setjmp()-longjmp() pair cannot be intermixed. A stack environment and signal mask saved by sigsetjmp() can be restored only by siglongjmp().


Related Information


Example

Note: By using the code examples, you agree to the terms of the Code license and disclaimer information.

This example saves the stack environment and signal mask at the following statement: Start of change

    returnCode = sigsetjmp( mark, 1 );

When the system first performs the sigsetjmp(), it saves the environment and signal mask in mark and sets returnCode to 0 because sigsetjmp() returns a 0 when it saves the environment. The program prints the following message:

    sigsetjmp() has been called

The subsequent call to function p() tests for a local error condition, which can cause it to perform siglongjmp() (in this example as a result of calling a signal catching function). Control is returned to the original sigsetjmp() function using the environment saved in mark and the restored signal mask. This time, returnCode contains -1 because this is the return value from siglongjmp().

The program then performs the statements for the case -1 leg of the switch statement and prints the following message:

    siglongjmp() function was called

A test is performed to demonstrate that the signal mask was restored and prints the following:

    signal mask was restored after siglongjmp()

Then the program exits. End of change

Here is the program:

Start of change
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>
#include <stdio.h>

sigset_t sigset;
sigjmp_buf mark;
int catcherWasCalled;

void catcher( int );
void p( void );

int main( int argc, char *argv[] ) {

    int result = 0;
    int returnCode = 0;

    /*
     * Block the SIGUSR2 signal.  This signal set will be
     * saved as part of the environment by the sigsetjmp()
     * function and subsequently restored by the siglongjmp()
     * function.
     */

     sigemptyset( &sigset );
     sigaddset( &sigset, SIGUSR2 );
     sigprocmask( SIG_SETMASK, &sigset, NULL );

     /* Save the stack environment and the current signal mask */
   
     returnCode = sigsetjmp( mark, 1 );

     /* Handle the sigsetjmp return code */

     switch ( returnCode ) {

	 case  0 : {
             printf( "sigsetjmp() has been called\n" );

            /*
             * Call function p() which will call the siglongjmp() 
             * function
             */

             p();

             printf( "control returning here is an error\n" );
             result=-1;
             break;
	 }

	 case -1 : {
             printf( "siglongjmp() function was called\n" );

             /* Retrieve the current signal mask */
           
             sigprocmask( SIG_SETMASK, NULL, &sigset );

             /* Verify SIGUSR2 is in sigset */
	     if( sigismember( &sigset, SIGUSR2 ) ) {
               printf( "signal mask was restored after siglongjmp()\n" );
               result=0;
	     }
	     else {
               printf( "signal mask was not restored after siglongjmp()\n" );
               result=-1;
	     }
             break;
	 }

	 default: {
             printf( "this unexpected return code is an error\n" );
             result=-1;
             break;
	 }
     }

    printf( "return from main with result %d\n", result );

    return( result );
}

void p( void ) {

    struct sigaction sigact;
    int error=0;

    printf( "performing function p()\n" );

    /* Setup signal handler in case error condition is detected */

    sigemptyset( &sigact.sa_mask );
    sigact.sa_flags = 0;
    sigact.sa_handler = catcher;
    sigaction( SIGUSR2, &sigact, NULL );

   /*
    * Delete SIGUSR2 from the signal set that was initialized
    * by the main() function. This allows us to demonstrate
    * that the original signal set saved by the sigsetjmp() function
    * is restored by the siglongjmp() function.
    */

    sigdelset( &sigset, SIGUSR2 );
    sigprocmask( SIG_SETMASK, &sigset, NULL );

    /* After some processing an error condition is detected */

    error=-1;

    /* Call catcher() function if error is detected */

    if( error != 0 ) {
        catcherWasCalled = 0;

        /* Send SIGUSR2 to handle the error condition */

        printf( "error condition detected, send SIGUSR2 signal\n" );
        kill( getpid(), SIGUSR2 );

	if( catcherWasCalled == 1 ) {

            printf( "catcher() function handled the error condition\n" );

           /*
            * Perform a nonlocal "goto" and specify -1 for the
            * return value
            */

            siglongjmp( mark, -1 );

            printf( "control getting here is an error\n" );
	}
    }
}

void catcher( int signo ) {

   /*
    * Indicate the catcher() function is handling the
    * SIGUSR2 signal.
    */

    catcherWasCalled = 1;
}

Output

    sigsetjmp() has been called
    performing function p()
    error condition detected, send SIGUSR2 signal
    catcher() function handled the error condition
    siglongjmp() function was called
    signal mask was restored after siglongjmp()
    return from main with result 0

End of change

API introduced: V3R6

[ Back to top | UNIX-Type APIs | APIs by category ]