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

Diff of /trunk/ascend/utilities/ascSignal.c

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

revision 2534 by jpye, Sun Oct 9 03:49:49 2011 UTC revision 2535 by jpye, Thu Jan 26 00:19:50 2012 UTC
# Line 39  Line 39 
39                    to local arrays.  gl_list's can't legally hold                    to local arrays.  gl_list's can't legally hold
40                    function pointers. (JDS)                    function pointers. (JDS)
41      18 Dec 06   - Removed ascresetneeded (moved to SConstruct)      18 Dec 06   - Removed ascresetneeded (moved to SConstruct)
42        25 Jan 12   - Add debug capability for contents of stacks (JDP)
43  */  */
44    
45  #include "ascSignal.h"  #include "ascSignal.h"
# Line 66  Line 67 
67  #include "ascSignal.h"  #include "ascSignal.h"
68  #include <ascend/general/panic.h>  #include <ascend/general/panic.h>
69    
70  /* #define SIGNAL_DEBUG */  //#define SIGNAL_DEBUG
71    
72  /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
73    GLOBALS AND FOWARD DECS    GLOBALS AND FOWARD DECS
# Line 84  fenv_t g_fenv; Line 85  fenv_t g_fenv;
85  /* for future use */  /* for future use */
86  jmp_buf g_foreign_code_call_env;  jmp_buf g_foreign_code_call_env;
87    
88    /**
89        Struct to store signal stacks, with support for debugging names and
90        location where handlers were pushed.
91    */
92    typedef struct{
93        SigHandlerFn *handler;
94    #ifdef SIGNAL_DEBUG
95        char *name;
96        char *file;
97        int line;
98    #endif
99    } SignalStackItem;
100    
101    typedef struct{
102        SignalStackItem fpe_traps[MAX_TRAP_DEPTH];
103        int fpe_top;
104        SignalStackItem int_traps[MAX_TRAP_DEPTH];
105        int int_top;
106        SignalStackItem seg_traps[MAX_TRAP_DEPTH];
107        int seg_top;
108    } SignalStacks;
109    
110    static SignalStacks *f_traps = NULL;
111    
112    #if 0
113  static SigHandlerFn **f_fpe_traps = NULL;  /**< array for pushed SIGFPE handlers */  static SigHandlerFn **f_fpe_traps = NULL;  /**< array for pushed SIGFPE handlers */
114  static int f_fpe_top_of_stack = -1;     /**< top of SIGFPE stack, -1 for empty */  static int f_fpe_top_of_stack = -1;     /**< top of SIGFPE stack, -1 for empty */
115    
# Line 92  static int f_int_top_of_stack = -1; Line 118  static int f_int_top_of_stack = -1;
118    
119  static SigHandlerFn **f_seg_traps = NULL;  /**< array for pushed SIGSEGV handlers */  static SigHandlerFn **f_seg_traps = NULL;  /**< array for pushed SIGSEGV handlers */
120  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 */
121    #endif
122    
123  #ifdef HAVE_C99FPE  #ifdef HAVE_C99FPE
124  static fenv_t *f_fenv_stack = NULL;  static fenv_t *f_fenv_stack = NULL;
125  static int f_fenv_stack_top = -1;  static int f_fenv_stack_top = -1;
126  #endif  #endif
127    
128  static void initstack (SigHandlerFn **traps, int *stackptr, int sig);  static void initstack(int sig);
129  static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);  static int pop_trap(int signum, SigHandlerFn *tp, char *name, char *file, int line);
130  static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp);  static int push_trap(int signum, SigHandlerFn *func, char *name, char *file, int line);
131  static void reset_trap(int signum, SigHandlerFn **tlist, int tos);  static void reset_trap(int signum);
 static void print_stack(int signum, SigHandlerFn **tlist, int tos);  
132    
133  #ifdef HAVE_C99FPE  #ifdef HAVE_C99FPE
134  static int fenv_pop(fenv_t *stack, int *top);  static int fenv_pop(fenv_t *stack, int *top);
135  static int fenv_push(fenv_t *stack,int *top, int excepts);  static int fenv_push(fenv_t *stack,int *top, int excepts);
136  #endif  #endif
137    
138    #define SIGNAME(SIGNUM) (SIGNUM==SIGFPE?"SIGFPE":(SIGNUM==SIGINT?"SIGINT":(SIGNUM==SIGSEGV?"SIGSEGV":"unknown")))
139  /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
140    API FUNCTIONS    API FUNCTIONS
141  */  */
# Line 123  static int fenv_push(fenv_t *stack,int * Line 150  static int fenv_push(fenv_t *stack,int *
150    
151      @return 0 if successful, 1 if out of memory, 2 otherwise.      @return 0 if successful, 1 if out of memory, 2 otherwise.
152  */  */
153  int Asc_SignalInit(void)  int Asc_SignalInit(void){
 {  
154    /* initialize SIGFPE stack */    /* initialize SIGFPE stack */
155    
156  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
157    CONSOLE_DEBUG("Initialising signal stack");  # ifdef ASC_RESETNEEDED
158      CONSOLE_DEBUG("Initialising signal stack (with resets needed)");
159    # else
160      CONSOLE_DEBUG("Initialising signal stack (with resets not required)");
161    # endif
162  #endif  #endif
163    
164    if (f_fpe_traps == NULL) {    if(f_traps == NULL){
165      f_fpe_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);      f_traps = ASC_NEW(SignalStacks);
166      if (f_fpe_traps == NULL) {      if(!f_traps){
167        return 1;        return 1;
168      }      }
169        f_traps->fpe_top = -1;
170        f_traps->int_top = -1;
171        f_traps->seg_top = -1;
172    }    }
   f_fpe_top_of_stack = -1;  
173    
174  #ifdef HAVE_C99FPE  #ifdef HAVE_C99FPE
175    if(f_fenv_stack==NULL){ /* if we haven't already initialised this... */    if(f_fenv_stack==NULL){ /* if we haven't already initialised this... */
# Line 149  int Asc_SignalInit(void) Line 181  int Asc_SignalInit(void)
181    f_fenv_stack_top = -1;    f_fenv_stack_top = -1;
182  #endif  #endif
183    
   /* initialize SIGINT stack */  
   if (f_int_traps == NULL) {  
     f_int_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);  
     if(f_int_traps == NULL){  
       /* failed malloc: free the earlier stuff */  
       ASC_FREE(f_fpe_traps);  
       f_fpe_traps = NULL;  
       return 1;  
     }  
   }  
   f_int_top_of_stack = -1;  
   
   /* initialize SIGSEGV stack */  
   if (f_seg_traps == NULL) {  
     f_seg_traps = ASC_NEW_ARRAY_CLEAR(SigHandlerFn*,MAX_TRAP_DEPTH);  
     if (f_seg_traps == NULL) {  
       /* failed malloc: free the earlier stuff */  
       ASC_FREE(f_fpe_traps);  
       f_fpe_traps = NULL;  
       ASC_FREE(f_int_traps);  
       f_int_traps = NULL;  
       return 1;  
     }  
   }  
   f_seg_top_of_stack = -1;  
   
184    /* old signals are *not* stored */    /* old signals are *not* stored */
185    initstack(f_fpe_traps, &f_fpe_top_of_stack, SIGFPE);    initstack(SIGFPE);
186    initstack(f_int_traps, &f_int_top_of_stack, SIGINT);    initstack(SIGINT);
187    initstack(f_seg_traps, &f_seg_top_of_stack, SIGSEGV);    initstack(SIGSEGV);
188    
189  #if defined(HAVE_C99FPE)  #if defined(HAVE_C99FPE)
190    CONSOLE_DEBUG("Initialise FPE state to stack (%d)",f_fenv_stack_top);    CONSOLE_DEBUG("Initialise FPE state to stack (%d)",f_fenv_stack_top);
# Line 193  int Asc_SignalInit(void) Line 199  int Asc_SignalInit(void)
199  */  */
200  void Asc_SignalDestroy(void)  void Asc_SignalDestroy(void)
201  {  {
202    ascfree(f_fpe_traps);    ascfree(f_traps);
   ascfree(f_int_traps);  
   ascfree(f_seg_traps);  
203  #ifdef HAVE_C99FPE  #ifdef HAVE_C99FPE
204    if(f_fenv_stack){    if(f_fenv_stack){
205      ASC_FREE(f_fenv_stack);      ASC_FREE(f_fenv_stack);
206      f_fenv_stack = NULL;      f_fenv_stack = NULL;
207    }    }
208  #endif  #endif
209    f_fpe_traps = f_int_traps = f_seg_traps =  NULL;    f_traps = NULL;
   f_fpe_top_of_stack = f_int_top_of_stack = f_seg_top_of_stack =  -1;  
   
210  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
211    CONSOLE_DEBUG("Destroyed signal stack");    CONSOLE_DEBUG("Destroyed signal stack");
212  #endif  #endif
# Line 228  void Asc_SignalRecover(int force){ Line 230  void Asc_SignalRecover(int force){
230  # ifdef SIGNAL_DEBUG  # ifdef SIGNAL_DEBUG
231          CONSOLE_DEBUG("Resetting traps");          CONSOLE_DEBUG("Resetting traps");
232  # endif  # endif
233          reset_trap(SIGFPE, f_fpe_traps, f_fpe_top_of_stack);          reset_trap(SIGFPE);
234          reset_trap(SIGINT, f_int_traps, f_int_top_of_stack);          reset_trap(SIGINT);
235          reset_trap(SIGSEGV, f_seg_traps, f_seg_top_of_stack);          reset_trap(SIGSEGV);
236  #ifndef ASC_RESETNEEDED  #ifndef ASC_RESETNEEDED
237      }      }
238  #endif  #endif
239  }  }
240    
 int Asc_SignalHandlerPushDefault(int signum){  
     return Asc_SignalHandlerPush(signum, &Asc_SignalTrap);  
 }  
   
241  /**  /**
242      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.
243    
# Line 249  int Asc_SignalHandlerPushDefault(int sig Line 247  int Asc_SignalHandlerPushDefault(int sig
247      On a successful return, the handler has been installed and will      On a successful return, the handler has been installed and will
248      remain installed until a Asc_SignalHandlerPop or another push.      remain installed until a Asc_SignalHandlerPop or another push.
249    
250      @return 0 on success, -2 if tp is NULL, -1 if unsupported signal is given,      @return 0 on success, -2 if func is NULL, -1 if unsupported signal is given,
251      -3 if 'signal' returns SIG_ERR.      -3 if 'signal' returns SIG_ERR.
252  */  */
253  int Asc_SignalHandlerPush(int signum, SigHandlerFn *tp)  int Asc_SignalHandlerPush_impl(int signum, SigHandlerFn *func, char *name
254  {      , char *file, int line
255    ){
256    int err;    int err;
257    if (tp == NULL) {    if (func == NULL) {
258      return -2;      return -2;
259    }    }
260    
261  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
262    CONSOLE_DEBUG("Pushing handler at %p for signal %d",tp,signum);    CONSOLE_DEBUG("Pushing handler %s for signal %s(%d)"
263        ,name,SIGNAME(signum),signum
264      );
265  #endif  #endif
266    
267    switch (signum) {    err = push_trap(signum, func, name, file, line);
268      case SIGFPE:  
       //CONSOLE_DEBUG("PUSH SIGFPE");  
       err = push_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);  
 #if 0 && defined(HAVE_C99FPE)  
       if(tp == SIG_IGN){  
           err = fenv_push(f_fenv_stack, &f_fenv_stack_top,FE_ALL_EXCEPT);  
       }else{  
           err = fenv_push(f_fenv_stack, &f_fenv_stack_top,0);  
       }  
 #endif  
       break;  
     case SIGINT:  
 #ifdef SIGNAL_DEBUG  
       CONSOLE_DEBUG("PUSH SIGINT");  
 #endif  
       err = push_trap(f_int_traps, &f_int_top_of_stack, tp);  
       break;  
     case SIGSEGV:  
       /* CONSOLE_DEBUG("PUSH SIGSEGV"); */  
       err = push_trap(f_seg_traps, &f_seg_top_of_stack, tp);  
       break;  
     default:  
       return -1;  
   }  
269    if(err != 0){    if(err != 0){
270      ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Error from push_trap or fenv_push (err = %d, signal=#%d).",err, signum);      ERROR_REPORTER_HERE(ASC_PROG_ERROR,"Error pushing %s to stack (err = %d, signal=%s(%d))."
271          ,name, err, SIGNAME(signum), signum
272        );
273      return err;      return err;
274    }    }
275    return SIG_ERR==SIGNAL(signum, tp); /* install */    return SIG_ERR==SIGNAL(signum, func); /* install */
276  }  }
277    
 int Asc_SignalHandlerPopDefault(int signum){  
     return Asc_SignalHandlerPop(signum, &Asc_SignalTrap);  
 }  
278    
279  /* see ascSignal.h */  int Asc_SignalHandlerPop_impl(int signum, SigHandlerFn *tp, char *name
280  int Asc_SignalHandlerPop(int signum, SigHandlerFn *tp){      , char *file, int line
281    ){
282    int err;    int err;
283  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
284    CONSOLE_DEBUG("Popping signal stack for signal %d (expecting top to be %p)",signum,tp);    CONSOLE_DEBUG("(%s:%d) Popping signal stack for signal %s (%d) (expecting top to be %p '%s')",file,line,SIGNAME(signum),signum,tp,name);
285  #endif  #endif
286    
287    switch (signum) {    err = pop_trap(signum, tp, name, file, line);
288    case SIGFPE:  
 #ifdef SIGNAL_DEBUG  
     CONSOLE_DEBUG("POP SIGFPE");  
 #endif  
     err = pop_trap(f_fpe_traps, &f_fpe_top_of_stack, tp);  
 #if 0 && defined(HAVE_C99FPE)  
     if(!err){  
         err = fenv_pop(f_fenv_stack, &f_fenv_stack_top);  
     }  
 #endif  
     break;  
   case SIGINT:  
 #ifdef SIGNAL_DEBUG  
     CONSOLE_DEBUG("POP SIGINT");  
 #endif  
     err = pop_trap(f_int_traps, &f_int_top_of_stack, tp);  
     break;  
   case SIGSEGV:  
 #ifdef SIGNAL_DEBUG  
     CONSOLE_DEBUG("POP SIGSEGV");  
 #endif  
     err = pop_trap(f_seg_traps, &f_seg_top_of_stack, tp);  
     break;  
   default:  
     ERROR_REPORTER_HERE(ASC_PROG_ERR,"Popping invalid signal type (signum = %d)", signum);  
     return -1;  
   }  
289    if (err != 0 && tp != NULL) {    if (err != 0 && tp != NULL) {
290  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
291      CONSOLE_DEBUG("stack pop mismatch");      CONSOLE_DEBUG("stack pop mismatch");
# Line 342  int Asc_SignalHandlerPop(int signum, Sig Line 294  int Asc_SignalHandlerPop(int signum, Sig
294      return err;      return err;
295    }    }
296    SIGNAL(signum,Asc_SignalStackTop(signum));    SIGNAL(signum,Asc_SignalStackTop(signum));
297    return 0;    return err;
298  }  }
299    
300  void Asc_SignalTrap(int sigval){  void Asc_SignalTrap(int sigval){
# Line 351  void Asc_SignalTrap(int sigval){ Line 303  void Asc_SignalTrap(int sigval){
303  #endif  #endif
304    switch(sigval) {    switch(sigval) {
305    case SIGFPE:    case SIGFPE:
306      ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Floating point error caught");      ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Floating point error caught");
307      CONSOLE_DEBUG("SIGFPE caught");      CONSOLE_DEBUG("SIGFPE caught");
308  #ifdef HAVE_C99FPE  #ifdef HAVE_C99FPE
309      FPRESET;      FPRESET;
310  #endif  #endif
311      LONGJMP(g_fpe_env,sigval);      LONGJMP(g_fpe_env,sigval);
     break;  
312    case SIGINT:    case SIGINT:
313      CONSOLE_DEBUG("SIGINT (Ctrl-C) caught");      CONSOLE_DEBUG("SIGINT (Ctrl-C) caught");
314      LONGJMP(g_int_env,sigval);      LONGJMP(g_int_env,sigval);
     break;  
315    case SIGSEGV:    case SIGSEGV:
316      CONSOLE_DEBUG("SIGSEGV caught");  #ifdef SIGNAL_DEBUG
317        CONSOLE_DEBUG("SIGSEGV caught");
318    #endif
319      LONGJMP(g_seg_env,sigval);      LONGJMP(g_seg_env,sigval);
     break;  
320    default:    default:
321    #ifdef SIGNAL_DEBUG
322        CONSOLE_DEBUG("Unrecognised signal %d caught",sigval);
323    #endif
324      ERROR_REPORTER_HERE(ASC_PROG_ERR,"Installed on unexpected signal (sigval = %d). Returning (who knows where...)", sigval);      ERROR_REPORTER_HERE(ASC_PROG_ERR,"Installed on unexpected signal (sigval = %d). Returning (who knows where...)", sigval);
325        return;
     break;  
326    }    }
   CONSOLE_DEBUG("Returning ... who knows where :-)");  
   return;  
327  }  }
328    
329  void Asc_SignalPrintStack(int signum){  void Asc_SignalPrintStack(int signum){
330        if(!f_traps){
331            ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler not initialised!");
332            return;
333        }
334        SignalStackItem *stack;
335        int *index;
336      switch(signum){      switch(signum){
337          case SIGINT:          case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
338              print_stack(SIGINT,f_int_traps,f_int_top_of_stack);          case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
339              return;          case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
         case SIGFPE:  
             print_stack(SIGFPE,f_fpe_traps,f_fpe_top_of_stack);  
             return;  
         case SIGSEGV:  
             print_stack(SIGSEGV,f_seg_traps,f_seg_top_of_stack);  
             return;  
340          default:          default:
341              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal %d",signum);              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
342                return;
343        }
344        int i = 0;
345        const char *signame = (signum==SIGFPE?"SIGFPE":SIGNAME(signum));
346        
347    #define LMAX 4096
348        char str[LMAX], *end = str;
349        int ch;
350        if(*index == -1){
351            fprintf(stderr,"%s handler stack: empty\n",signame);
352        }else{
353            for(i = 0; i <= *index; ++i){
354    #ifdef SIGNAL_DEBUG
355                ch = SNPRINTF(end, LMAX - (end - str), "%s  ", stack[i].name);
356    #else
357                ch = SNPRINTF(end, LMAX - (end - str), "%p  ", stack[i].handler);
358    #endif
359                end += ch;
360                if(ch<0)break;
361            }
362            fprintf(stderr,"%s handler stack: %s\n",signame,str);
363      }      }
364  }  }
365    
366  int Asc_SignalStackLength(int signum){  int Asc_SignalStackLength(int signum){
367        int *index;
368      switch(signum){      switch(signum){
369          case SIGINT:          case SIGFPE: index = &(f_traps->fpe_top); break;
370              return f_int_top_of_stack + 1;          case SIGINT: index = &(f_traps->int_top); break;
371          case SIGFPE:          case SIGSEGV: index = &(f_traps->seg_top); break;
             return f_fpe_top_of_stack + 1;  
         case SIGSEGV:  
             return f_seg_top_of_stack + 1;  
372          default:          default:
373              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal %d",signum);              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d",signum);
374              return 0;              return 0;
375      }      }
376        return *index + 1;
377  }  }
378    
379  SigHandlerFn *Asc_SignalStackTop(int signum){  SigHandlerFn *Asc_SignalStackTop(int signum){
380      SigHandlerFn **stack;      if(!f_traps)return NULL;
381      int *ptr;      SignalStackItem *stack;
382        int *index;
383      switch(signum){      switch(signum){
384          case SIGINT:          case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
385              stack = f_int_traps; ptr = &f_int_top_of_stack; break;          case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
386          case SIGFPE:          case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
387              stack = f_fpe_traps; ptr = &f_fpe_top_of_stack; break;          default:
388          case SIGSEGV:              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
389              stack = f_seg_traps; ptr = &f_seg_top_of_stack; break;              return NULL;
390      }      }
391      if(stack==NULL)return NULL;      if(*index < 0)return NULL;
392      if(ptr==NULL)return NULL;      if(*index >= MAX_TRAP_DEPTH)return NULL;
393      if(*ptr < 0) return NULL;      return stack[*index].handler;
     if(*ptr >= MAX_TRAP_DEPTH) return NULL;  
     return stack[*ptr];  
394  }  }
395    
396  /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
# Line 451  SigHandlerFn *Asc_SignalStackTop(int sig Line 421  SigHandlerFn *Asc_SignalStackTop(int sig
421  //------------------------------------  //------------------------------------
422  // COMMOM STACK ROUTINES (shared by the three different signal handler stacks)  // COMMOM STACK ROUTINES (shared by the three different signal handler stacks)
423    
424  static void initstack(SigHandlerFn **traps, int *stackptr, int sig){  static void initstack(int sig){
425    SigHandlerFn *old;      SigHandlerFn *old;
426    old = SIGNAL(sig,SIG_DFL);      SignalStackItem *stack;
427    if (old != SIG_ERR && old != SIG_DFL){      int *index;
428        switch(sig){
429            case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
430            case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
431            case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
432            default:
433                ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", sig);
434                return;
435        }
436        old = SIGNAL(sig, SIG_DFL);
437        if(old != SIG_ERR && old != SIG_DFL){
438  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
439      CONSOLE_DEBUG("Initialising stack for signal %d to %p",sig,old);          CONSOLE_DEBUG("Initialising stack for signal %d to %p",sig,old);
440  #endif  #endif
441      traps[0] = old;          stack[0].handler = old;
     *stackptr = 0;  
     (void)SIGNAL(sig,old);  
   }else{  
442  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
443      CONSOLE_DEBUG("Initialising stack for signal %d as empty",sig);          if(old == SIG_DFL){
444                stack[0].name = "SIG_DFL";
445            }else{
446                stack[0].name = "preexisting";
447            }
448            stack[0].file = "unknown";
449            stack[0].line = 0;
450  #endif  #endif
451      *stackptr = -1;          *index = 0;
452    }          (void)SIGNAL(sig,old);
453  }      }else{
   
 static void reset_trap(int signum, SigHandlerFn **tlist, int tos){  
   SigHandlerFn *tp;  
   SigHandlerFn *oldfn;  
   if ((tlist != NULL) && (tos >= 0) && (tos < MAX_TRAP_DEPTH)) {  
     oldfn = signal(signum,SIG_DFL);  
     tp = tlist[tos];  
     if (tp != SIG_ERR) {  
 #ifndef ASC_RESETNEEDED  
       if(tp!=oldfn){  
454  #ifdef SIGNAL_DEBUG  #ifdef SIGNAL_DEBUG
455          ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Resetting signal %d (was=%p, new=%p",signum,oldfn,tp);          CONSOLE_DEBUG("Initialising stack for signal %d as empty",sig);
 #endif  
       }  
456  #endif  #endif
457        (void)signal(signum,tp);          *index = -1;
458      }      }
459    }else{  }
460      (void)SIGNAL(signum,SIG_DFL);  
461    }  static void reset_trap(int signum){
462        SignalStackItem top;
463        SigHandlerFn *oldfn;
464    
465        if(f_traps){
466            SignalStackItem *stack;
467            int *index;
468            switch(signum){
469                case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
470                case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
471                case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
472                default:
473                    ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
474                    return;
475            }
476            if(*index >= 0 && *index < MAX_TRAP_DEPTH){
477                oldfn = signal(signum,SIG_DFL); (void)oldfn;
478                top = stack[*index];
479                if(top.handler != SIG_ERR && top.handler != SIG_DFL){
480                    /* reset the signal, if it's not already set to what we want */
481    #ifdef SIGNAL_DEBUG
482                    CONSOLE_DEBUG("Resetting signal %s from %p to %p (%s)"
483                        ,SIGNAME(signum)
484                        ,oldfn,top.handler,top.name
485                    );
486    #endif
487                    (void)SIGNAL(signum,top.handler);
488                    return;
489                }
490            }
491    #ifdef SIGNAL_DEBUG
492            CONSOLE_DEBUG("Resetting %s handler to SIG_DFL (stack empty or invalid)"
493                ,SIGNAME(signum)
494            );
495    #endif
496            (void)SIGNAL(signum,SIG_DFL);
497        }else{
498            ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler not yet initialised! Setting %s handler to SIG_DFL.",SIGNAME(signum));
499            (void)SIGNAL(signum,SIG_DFL);
500            return;
501        }
502  }  }
503    
504  /**  /**
505      Append a pointer to the list given, if the list is not full.      Append a pointer to the list given, if the list is not full.
506  */  */
507  static int push_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){  static int push_trap(int signum, SigHandlerFn *func, char *name, char *file, int line){
508    if (tlist == NULL) {      if(!f_traps){
509      ERROR_REPORTER_HERE(ASC_PROG_ERR,"TLIST is NULL");          ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler list f_traps not initialised");
510      return -1;          return -1;
511    }      }
512    if (stackptr == NULL) {      SignalStackItem *stack;
513      ERROR_REPORTER_HERE(ASC_PROG_ERR,"STACKPTR is NULL");      int *index;
514      return -1;      switch(signum){
515    }          case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
516    if (tp == NULL) {          case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
517      ERROR_REPORTER_HERE(ASC_PROG_ERR,"TP is NULL");          case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
518      return 2;          default:
519    }              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
520    if (*stackptr > MAX_TRAP_DEPTH-1) {              return -2;
521      ERROR_REPORTER_HERE(ASC_PROG_ERR,"stackptr >= capacity");      }
522      return 1;  
523    }      if (*index > MAX_TRAP_DEPTH-1) {
524    ++(*stackptr);          ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler stack for %s is full!"
525    tlist[*stackptr] = tp;              ,SIGNAME(signum)
526    return 0;          );
527            return 1;
528        }
529        ++(*index);
530        stack[*index].handler = func;
531    #ifdef SIGNAL_DEBUG
532        stack[*index].name = name;
533        stack[*index].file = file;
534        stack[*index].line = line;
535    #endif
536        return 0;
537  }  }
538    
539    
# Line 522  static int push_trap(SigHandlerFn **tlis Line 543  static int push_trap(SigHandlerFn **tlis
543    
544      Any non-zero return code leaves the stack as it was.      Any non-zero return code leaves the stack as it was.
545  */  */
546  static int pop_trap(SigHandlerFn **tlist, int *stackptr, SigHandlerFn *tp){  static int pop_trap(int signum, SigHandlerFn *func, char *name, char *file, int line){
547    SigHandlerFn *oldtrap;      int err = 0;
548        if(!f_traps){
549    if ((tlist == NULL) || (stackptr == NULL)) {          ERROR_REPORTER_HERE(ASC_PROG_ERR,"Signal handler list f_traps not initialised");
550      return 2;          return 2;
551    }      }
552    if (*stackptr < 0) {      SignalStackItem *stack;
553      return 1;      int *index;
554    }      switch(signum){
555    oldtrap = tlist[*stackptr];          case SIGFPE: stack = f_traps->fpe_traps; index = &(f_traps->fpe_top); break;
556    if(oldtrap != tp)return -1;          case SIGINT: stack = f_traps->int_traps; index = &(f_traps->int_top); break;
557    tlist[*stackptr] = NULL;          case SIGSEGV: stack = f_traps->seg_traps; index = &(f_traps->seg_top); break;
558    --(*stackptr);          default:
559    return 0;              ERROR_REPORTER_HERE(ASC_PROG_ERR,"Invalid signal code %d", signum);
560  }              return 3;
561        }
562    
563  static void print_stack(int signum, SigHandlerFn **tlist, int tos){      if(*index < 0)return 1;
564      int i;      
565      CONSOLE_DEBUG("---------------");      if(stack[*index].handler != func){
566      for(i=0;i<=tos;++i){  #ifdef SIGNAL_DEBUG
567          CONSOLE_DEBUG("Signal #%d, stack %d/%d: %p",signum,i,tos,tlist[i]);          error_reporter(ASC_PROG_ERR,file,line,name,"Request to pop '%s' (%p), but top of stack contains '%s' (%p)!"
568                ,name,func,stack[*index].name,stack[*index].handler
569            );
570    #else
571            ERROR_REPORTER_HERE(ASC_PROG_ERR,"Request to pop handler %p, but top of stack contains %p!"
572                ,func,stack[*index].handler
573            );
574    #endif
575            err = 4;
576      }      }
577      CONSOLE_DEBUG("--------------- = %d",tos);      stack[*index].handler = NULL;
578    #ifdef SIGNAL_DEBUG
579        stack[*index].name = NULL;
580        stack[*index].file = NULL;
581        stack[*index].line = 0;
582    #endif
583        --(*index);
584        return err;
585  }  }
586    
587  /*------------------------------------------  /*------------------------------------------

Legend:
Removed from v.2534  
changed lines
  Added in v.2535

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