and sigsetjmp

Team-FLY

8.7 Program Control with siglongjmp and sigsetjmp

Programs sometimes use signals to handle errors that are not fatal but that can occur in many places in a program. For example, a user might want to avoid terminating a program while aborting a long calculation or an I/O operation that has blocked for a long time. The program's response to Ctrl-C should be to start over at the beginning (or at some other specified location). A similar situation occurs when the program has nested prompts or menus and should start over when a user misenters a response. Object-oriented languages often handle these situations by throwing exceptions that are caught elsewhere. C programs can use signals indirectly or directly to handle this type of problem.

In the indirect approach, the signal handler for SIGINT sets a flag in response to Ctrl-C. The program tests the flag in strategic places and returns to the desired termination point if the flag is set. The indirect approach is complicated, since the program might have to return through several layers of functions. At each return layer, the program tests the flag for this special case.

In the direct approach, the signal handler jumps directly back to the desired termination point. The jump requires unraveling the program stack. A pair of functions, sigsetjmp and siglongjmp , provides this capability. The sigsetjmp function is analogous to a statement label, and siglongjmp function is analogous to a goto statement. The main difference is that the sigsetjmp and siglongjmp pair cleans up the stack and signal states as well as doing the jump.

Call the sigsetjmp at the point the program is to return to. The sigsetjmp provides a marker in the program similar to a statement label. The caller must provide a buffer, env , of type sigjmp_buf that sigsetjmp initializes to the collection of information needed for a jump back to that marker. If savemask is nonzero, the current state of the signal mask is saved in the env buffer. When the program calls sigsetjmp directly, it returns 0. To jump back to the sigsetjmp point from a signal handler, execute siglongjmp with the same sigjmp_buf variable. The call makes it appear that the program is returning from sigsetjmp with a return value of val .

  SYNOPSIS  #include <setjmp.h>   void siglongjmp(sigjmp_buf env, int val);   int sigsetjmp(sigjmp_buf env, int savemask);  POSIX:CX  

No errors are defined for siglongjmp . The sigsetjmp returns 0 when invoked directly and the val parameter value when invoked by calling siglongjmp .

The C standard library provides functions setjmp and longjmp for the types of jumps referred to above, but the action of these functions on the signal mask is system dependent. The sigsetjmp function allows the program to specify whether the signal mask should be reset when a signal handler calls this function. The siglongjmp function causes the signal mask to be restored if and only if the value of savemask is nonzero. The val parameter of siglongjmp specifies the value that is to be returned at the point set by sigsetjmp .

Program 8.12 sigjmp.c

Code to set up a signal handler that returns to the main loop when Ctrl-C is typed .

 #include <setjmp.h> #include <signal.h> #include <stdio.h> #include <unistd.h> static sigjmp_buf jmpbuf; static volatile sig_atomic_t jumpok = 0; /* ARGSUSED */ static void chandler(int signo) {     if (jumpok == 0) return;     siglongjmp(jmpbuf, 1); } int main(void)  {     struct sigaction act;     act.sa_flags = 0;     act.sa_handler = chandler;     if ((sigemptyset(&act.sa_mask) == -1)            (sigaction(SIGINT, &act, NULL) == -1)) {         perror("Failed to set up SIGINT handler");         return 1;     }                                                   /* stuff goes here */     fprintf(stderr, "This is process %ld\n", (long)getpid());     if (sigsetjmp(jmpbuf, 1))         fprintf(stderr, "Returned to main loop due to ^c\n");     jumpok = 1;     for ( ; ; )         ;                                       /* main loop goes here */ } 

Program 8.12 shows how to set up a SIGINT handler that causes the program to return to the main loop when Ctrl-C is typed. It is important to execute sigsetjmp before calling siglongjmp in order to establish a point of return. The call to sigaction should appear before the sigsetjmp so that it is called only once. To prevent the signal handler from calling siglongjmp before the program executes sigsetjmp , Program 8.12 uses the flag jumpok . The signal handler tests this flag before calling siglongjmp .

Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net