/[ascend]/trunk/base/generic/utilities/ascSignal.c
ViewVC logotype

Diff of /trunk/base/generic/utilities/ascSignal.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 955 by johnpye, Thu Dec 7 14:47:15 2006 UTC revision 956 by johnpye, Sat Dec 9 15:38:05 2006 UTC
# Line 31  Line 31 
31      by Benjamin Andrew Allan, May 27, 1997      by Benjamin Andrew Allan, May 27, 1997
32      Last in CVS $Revision: 1.9 $ $Date: 1999/01/19 12:23:20 $ $Author: mthomas $      Last in CVS $Revision: 1.9 $ $Date: 1999/01/19 12:23:20 $ $Author: mthomas $
33            
     ChangeLog  
   
34      10/15/2005  - Changed ascresetneeded() so that any previously      10/15/2005  - Changed ascresetneeded() so that any previously
35                    registered handlers are reset before return.                    registered handlers are reset before return.
36                  - Added Asc_SignalRecover() to standard handler                  - Added Asc_SignalRecover() to standard handler
# Line 59  Line 57 
57  #include "ascMalloc.h"  #include "ascMalloc.h"
58  #include "ascSignal.h"  #include "ascSignal.h"
59    
60    /*------------------------------------------------------------------------------
61      GLOBALS AND FOWARD DECS
62    */
63    
64  #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)  #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)
65  static jmp_buf f_test_env;    /* for local testing of signal handling */  static jmp_buf f_test_env;    /* for local testing of signal handling */
66  #endif  #endif
# Line 88  static int f_int_top_of_stack = -1; Line 90  static int f_int_top_of_stack = -1;
90  static SigHandlerFn **f_seg_traps = NULL;  /**< array for pushed SIGSEGV handlers */  static SigHandlerFn **f_seg_traps = NULL;  /**< array for pushed SIGSEGV handlers */
91  static int f_seg_top_of_stack = -1;     /**< top of SIGFPE stack, -1 for empty */  static int f_seg_top_of_stack = -1;     /**< top of SIGFPE stack, -1 for empty */
92    
93  #ifndef NO_SIGSEGV_TRAP  static int ascresetneeded(void);
94  /* function to throw an interrupt. system dependent. */  static void initstack (SigHandlerFn **traps, int *stackptr, int sig);
95  static int testdooley2(int sig){  static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);
96    raise(sig);  static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);
97    return 0;  static void reset_trap(int signum, SigHandlerFn **tlist, int tos);
 }  
 #endif  
   
 #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)  
 /* function to catch an interrupt */  
 static void testcatch(int signum){  
   FPRINTF(ASCERR," signal %d caught ",signum);  
   if (signum == SIGFPE) {  
     FPRESET;  
   }  
   longjmp(f_test_env, signum);  
 }  
 #endif  
   
 /*  
  * So far the following seem to need reset trapped signals after  
  * a longjmp, or unconditionally.  
  * HPUX cc -Aa -D_HPUX_SOURCE  
  * Solaris cc  
  * AIX xlc  
  * IRIX cc  
  * Windows  
  *  
  * The following retain the last trap set with or without a call to longjmp  
  * and so don't need resetting of traps.  
  * SunOS4 acc  
  * OSF32 cc  
  * NetBSD gcc 2.4.5 -ansi  
  */  
   
 /**  
     This function tests the signal reseting of compilers using SIGINT.  
     It should not be called except when starting a process.  
   
     Side effects:  
      - a line is sent to ASCERR  
      - SIGINT is set to SIG_DFL if no handler was previously registered  
      - SIGFPE may be set to SIG_DFL if no handler was previously registered  
98    
99      @return 0 for no reset needed, 1 for reset needed, and  /*------------------------------------------------------------------------------
100      -1 if the test fails (presuming program doesn't exit first.)    API FUNCTIONS
101  */  */
 static int ascresetneeded(void) {  
   static int result = 0;  
   
 #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)  
   SigHandlerFn *lasttrap;  
   volatile SigHandlerFn *savedtrap;  
   static int c=0;  
 #endif  
   
 #ifndef NO_SIGINT_TRAP  
   
   /* test interrupt */  
   savedtrap = signal(SIGINT, testcatch);  
   CONSOLE_DEBUG("Testing signal SIGINT (signum = %d) %p\t%p\t", SIGINT, savedtrap, testcatch);  
   if (setjmp(f_test_env) == 0) {  
     testdooley2(SIGINT);  
   } else {  
     c++;  
   }  
   if (c != 1) {  
     CONSOLE_DEBUG("SIGINT test failed");  
     ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Signal (SIGINT) test failed. ASCEND unlikely to work on this hardware.");  
     result = -1;  
   }  
   lasttrap = signal(SIGINT, (NULL != savedtrap) ? savedtrap : SIG_DFL);  
   CONSOLE_DEBUG("%p",lasttrap);  
   if (lasttrap != testcatch) {  
     result = 1;  
   }  
   
   if (result != 0) {  
     return result;  
   }  
   
   c = 0;  
 #else  
   CONSOLE_DEBUG("SIGINT trap bypassed: compile-time settings");  
 #endif  
   
 #ifndef NO_SIGSEGV_TRAP  
   /* passed interrupt, check fpe */  
   savedtrap=signal(SIGFPE, testcatch);  
   CONSOLE_DEBUG("Testing signal %d %p\t%p\t",SIGFPE, savedtrap, testcatch);  
   if (setjmp(f_test_env)==0) {  
     testdooley2(SIGFPE);  
   } else {  
     c++;  
   }  
   if (c != 1) {  
     CONSOLE_DEBUG("SIGFPE test failed");  
     ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Signal test failed. ASCEND unlikely to work on this hardware.");  
     result = -1;  
   }  
   lasttrap = signal(SIGFPE, (NULL != savedtrap) ? savedtrap : SIG_DFL);  
   CONSOLE_DEBUG("%p\n",lasttrap);  
   if (lasttrap != testcatch) {  
     result = 1;  
   }  
 #else  
   CONSOLE_DEBUG("SIGSEGV trap bypassed: compile-time settings.");  
 #endif  
   
   return result;  
 }  
   
 static void initstack (SigHandlerFn **traps, int *stackptr, int sig){  
   SigHandlerFn *old;  
   old = signal(sig,SIG_DFL);  
   if (old != SIG_ERR && old != SIG_DFL) {  
     traps[0] = old;  
     *stackptr = 0;  
     (void)signal(sig,old);  
   }  
 }  
102    
103  /**  /**
104      Initialise ASCEND signal handling      Initialise ASCEND signal handling
# Line 273  int Asc_SignalInit(void) Line 163  int Asc_SignalInit(void)
163    
164    f_reset_needed = ascresetneeded();    f_reset_needed = ascresetneeded();
165    if (f_reset_needed < 0) {    if (f_reset_needed < 0) {
166        CONSOLE_DEBUG("RESET NEEDED");
167      f_reset_needed = 1;      f_reset_needed = 1;
168      return 2;      return 2;
169    }    }
# Line 292  void Asc_SignalDestroy(void) Line 183  void Asc_SignalDestroy(void)
183    f_fpe_top_of_stack = f_int_top_of_stack = f_seg_top_of_stack =  -1;    f_fpe_top_of_stack = f_int_top_of_stack = f_seg_top_of_stack =  -1;
184  }  }
185    
186  static void reset_trap(int signum, SigHandlerFn **tlist, int tos)  /**
 {  
   SigHandlerFn *tp;  
   if ((tlist != NULL) && (tos >= 0) && (tos < MAX_TRAP_DEPTH)) {  
     tp = tlist[tos];  
     if (tp != SIG_ERR) {  
       (void)signal(signum,tp);  
     }  
   } else {  
     (void)signal(signum,SIG_DFL);  
   }  
 }  
 /*  
187      This function reinstalls all the signal handlers this module      This function reinstalls all the signal handlers this module
188      has been informed of. This should be called after every      has been informed of. This should be called after every
189      trapped exception and at any other time when the status of      trapped exception and at any other time when the status of
# Line 327  void Asc_SignalRecover(int force) Line 206  void Asc_SignalRecover(int force)
206  }  }
207    
208  /**  /**
     Append a pointer to the list given, if the list is not full.  
 */  
 static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp)  
 {  
   if (tlist == NULL) {  
     CONSOLE_DEBUG("TLIST IS NULL");  
     return -1;  
   }  
   if (stackptr == NULL) {  
     CONSOLE_DEBUG("STACKPTR IS NULL");  
     return -1;  
   }  
   if (tp == NULL) {  
     CONSOLE_DEBUG("TP IS NULL");  
     return 2;  
   }  
   if (*stackptr > MAX_TRAP_DEPTH-1) {  
     CONSOLE_DEBUG("TLIST LENGTH = CAPACITY");  
     return 1;  
   }  
   ++(*stackptr);  
   tlist[*stackptr] = tp;  
   return 0;  
 }  
   
 /*  
209      Add a handler to the stack of signal handlers for the given signal.      Add a handler to the stack of signal handlers for the given signal.
210    
211      There is a maximum stack limit, so returns 1 if limit exceeded.      There is a maximum stack limit, so returns 1 if limit exceeded.
# Line 369  int Asc_SignalHandlerPush(int signum, Si Line 222  int Asc_SignalHandlerPush(int signum, Si
222    }    }
223    switch (signum) {    switch (signum) {
224      case SIGFPE:      case SIGFPE:
225        /*ERROR_REPORTER_DEBUG("PUSH SIGFPE");*/        ERROR_REPORTER_DEBUG("PUSH SIGFPE");
226        err = push_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);        err = push_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);
227        break;        break;
228      case SIGINT:      case SIGINT:
229        /*ERROR_REPORTER_DEBUG("PUSH SIGINT");*/        ERROR_REPORTER_DEBUG("PUSH SIGINT");
230        err = push_trap(f_int_traps, &f_int_top_of_stack, tp);        err = push_trap(f_int_traps, &f_int_top_of_stack, tp);
231        break;        break;
232      case SIGSEGV:      case SIGSEGV:
233        /*ERROR_REPORTER_DEBUG("PUSH SIGSEGV");*/        ERROR_REPORTER_DEBUG("PUSH SIGSEGV");
234        err = push_trap(f_seg_traps, &f_seg_top_of_stack, tp);        err = push_trap(f_seg_traps, &f_seg_top_of_stack, tp);
235        break;        break;
236      default:      default:
# Line 391  int Asc_SignalHandlerPush(int signum, Si Line 244  int Asc_SignalHandlerPush(int signum, Si
244    return 0;    return 0;
245  }  }
246    
247  /*  /* see ascSignal.h */
     Returns: 0 -ok, 2 NULL list input, 1 empty list input,  
     -1 mismatched input tp and stack data.  
 */  
 static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){  
   SigHandlerFn *oldtrap;  
   
   if ((tlist == NULL) || (stackptr == NULL)) {  
     return 2;  
   }  
   if (*stackptr < 0) {  
     return 1;  
   }  
   oldtrap = tlist[*stackptr];  
   tlist[*stackptr] = NULL;  
   --(*stackptr);  
   return (-(oldtrap != tp));  
 }  
   
248  int Asc_SignalHandlerPop(int signum, SigHandlerFn *tp){  int Asc_SignalHandlerPop(int signum, SigHandlerFn *tp){
249    int err;    int err;
250    switch (signum) {    switch (signum) {
251    case SIGFPE:    case SIGFPE:
252      /*ERROR_REPORTER_DEBUG("POP SIGFPE");*/      ERROR_REPORTER_DEBUG("POP SIGFPE");
253      err = pop_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);      err = pop_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);
254      break;      break;
255    case SIGINT:    case SIGINT:
256      /*ERROR_REPORTER_DEBUG("POP SIGINT");*/      ERROR_REPORTER_DEBUG("POP SIGINT");
257      err = pop_trap(f_int_traps, &f_int_top_of_stack, tp);      err = pop_trap(f_int_traps, &f_int_top_of_stack, tp);
258      break;      break;
259    case SIGSEGV:    case SIGSEGV:
260      /*ERROR_REPORTER_DEBUG("POP SIGSEGV");*/      ERROR_REPORTER_DEBUG("POP SIGSEGV");
261      err = pop_trap(f_seg_traps, &f_seg_top_of_stack, tp);      err = pop_trap(f_seg_traps, &f_seg_top_of_stack, tp);
262      break;      break;
263    default:    default:
# Line 464  void Asc_SignalTrap(int sigval) { Line 299  void Asc_SignalTrap(int sigval) {
299     UNUSED_PARAMETER(sigval);     UNUSED_PARAMETER(sigval);
300  #endif /* NO_SIGNAL_TRAPS */  #endif /* NO_SIGNAL_TRAPS */
301  }  }
302    
303    /*------------------------------------------------------------------------------
304      UTILITY FUNCTIONS
305    */
306    
307    #ifndef NO_SIGSEGV_TRAP
308    /* function to throw an interrupt. system dependent. */
309    static int testdooley2(int sig){
310      raise(sig);
311      return 0;
312    }
313    #endif
314    
315    #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)
316    /* function to catch an interrupt */
317    static void testcatch(int signum){
318      FPRINTF(ASCERR," signal %d caught ",signum);
319      if (signum == SIGFPE) {
320        FPRESET;
321      }
322      longjmp(f_test_env, signum);
323    }
324    #endif
325    
326    /*
327     * So far the following seem to need reset trapped signals after
328     * a longjmp, or unconditionally.
329     * HPUX cc -Aa -D_HPUX_SOURCE
330     * Solaris cc
331     * AIX xlc
332     * IRIX cc
333     * Windows
334     *
335     * The following retain the last trap set with or without a call to longjmp
336     * and so don't need resetting of traps.
337     * SunOS4 acc
338     * OSF32 cc
339     * NetBSD gcc 2.4.5 -ansi
340     */
341    
342    /**
343        This function tests the signal reseting of compilers using SIGINT.
344        It should not be called except when starting a process.
345    
346        Side effects:
347         - a line is sent to ASCERR
348         - SIGINT is set to SIG_DFL if no handler was previously registered
349         - SIGFPE may be set to SIG_DFL if no handler was previously registered
350    
351        @return 0 for no reset needed, 1 for reset needed, and
352        -1 if the test fails (presuming program doesn't exit first.)
353    */
354    static int ascresetneeded(void) {
355      static int result = 0;
356    
357    #if !defined(NO_SIGINT_TRAP) || !defined(NO_SIGSEGV_TRAP)
358      SigHandlerFn *lasttrap;
359      volatile SigHandlerFn *savedtrap;
360      static int c=0;
361    #endif
362    
363    #ifndef NO_SIGINT_TRAP
364    
365      /* test interrupt */
366      savedtrap = signal(SIGINT, testcatch);
367      CONSOLE_DEBUG("Testing signal SIGINT (signum = %d) %p\t%p\t", SIGINT, savedtrap, testcatch);
368      if (setjmp(f_test_env) == 0) {
369        testdooley2(SIGINT);
370      } else {
371        c++;
372      }
373      if (c != 1) {
374        CONSOLE_DEBUG("SIGINT test failed");
375        ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Signal (SIGINT) test failed. ASCEND unlikely to work on this hardware.");
376        result = -1;
377      }
378      lasttrap = signal(SIGINT, (NULL != savedtrap) ? savedtrap : SIG_DFL);
379      CONSOLE_DEBUG("%p",lasttrap);
380      if (lasttrap != testcatch) {
381        result = 1;
382      }
383    
384      if (result != 0) {
385        return result;
386      }
387    
388      c = 0;
389    #else
390      CONSOLE_DEBUG("SIGINT trap bypassed: compile-time settings");
391    #endif
392    
393    #ifndef NO_SIGSEGV_TRAP
394      /* passed interrupt, check fpe */
395      savedtrap=signal(SIGFPE, testcatch);
396      CONSOLE_DEBUG("Testing signal %d %p\t%p\t",SIGFPE, savedtrap, testcatch);
397      if (setjmp(f_test_env)==0) {
398        testdooley2(SIGFPE);
399      } else {
400        c++;
401      }
402      if (c != 1) {
403        CONSOLE_DEBUG("SIGFPE test failed");
404        ERROR_REPORTER_NOLINE(ASC_PROG_ERROR,"Signal test failed. ASCEND unlikely to work on this hardware.");
405        result = -1;
406      }
407      lasttrap = signal(SIGFPE, (NULL != savedtrap) ? savedtrap : SIG_DFL);
408      CONSOLE_DEBUG("%p\n",lasttrap);
409      if (lasttrap != testcatch) {
410        result = 1;
411      }
412    #else
413      CONSOLE_DEBUG("SIGSEGV trap bypassed: compile-time settings.");
414    #endif
415    
416      return result;
417    }
418    
419    static void initstack (SigHandlerFn **traps, int *stackptr, int sig){
420      SigHandlerFn *old;
421      old = signal(sig,SIG_DFL);
422      if (old != SIG_ERR && old != SIG_DFL) {
423        traps[0] = old;
424        *stackptr = 0;
425        (void)signal(sig,old);
426      }
427    }
428    
429    static void reset_trap(int signum, SigHandlerFn **tlist, int tos){
430      SigHandlerFn *tp;
431      if ((tlist != NULL) && (tos >= 0) && (tos < MAX_TRAP_DEPTH)) {
432        tp = tlist[tos];
433        if (tp != SIG_ERR) {
434          (void)signal(signum,tp);
435        }
436      } else {
437        (void)signal(signum,SIG_DFL);
438      }
439    }
440    
441    /**
442        Append a pointer to the list given, if the list is not full.
443    */
444    static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){
445      if (tlist == NULL) {
446        CONSOLE_DEBUG("TLIST IS NULL");
447        return -1;
448      }
449      if (stackptr == NULL) {
450        CONSOLE_DEBUG("STACKPTR IS NULL");
451        return -1;
452      }
453      if (tp == NULL) {
454        CONSOLE_DEBUG("TP IS NULL");
455        return 2;
456      }
457      if (*stackptr > MAX_TRAP_DEPTH-1) {
458        CONSOLE_DEBUG("TLIST LENGTH = CAPACITY");
459        return 1;
460      }
461      ++(*stackptr);
462      tlist[*stackptr] = tp;
463      return 0;
464    }
465    
466    
467    /*
468        Returns: 0 -ok, 2 NULL list input, 1 empty list input,
469        -1 mismatched input tp and stack data.
470    */
471    static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){
472      SigHandlerFn *oldtrap;
473    
474      if ((tlist == NULL) || (stackptr == NULL)) {
475        return 2;
476      }
477      if (*stackptr < 0) {
478        return 1;
479      }
480      oldtrap = tlist[*stackptr];
481      tlist[*stackptr] = NULL;
482      --(*stackptr);
483      return (-(oldtrap != tp));
484    }

Legend:
Removed from v.955  
changed lines
  Added in v.956

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22