Actual source code: signal.c

  1: /*$Id: signal.c,v 1.76 2001/03/23 23:20:26 balay Exp $*/
  2: /*
  3:       Routines to handle signals the program will receive. 
  4:     Usually this will call the error handlers.
  5: */
  6: #include <signal.h>
 7:  #include petsc.h
 8:  #include petscsys.h
  9: #include "petscfix.h"     

 11: struct SH {
 12:   int    cookie;
 13:   int    (*handler)(int,void *);
 14:   void   *ctx;
 15:   struct SH* previous;
 16: };
 17: static struct SH* sh        = 0;
 18: static PetscTruth SignalSet = PETSC_FALSE;

 20: static char *SIGNAME[] = {
 21:     "Unknown signal",
 22:     "HUP",
 23:     "INT",
 24:     "QUIT",
 25:     "ILL",
 26:     "TRAP",
 27:     "ABRT",
 28:     "EMT",
 29:     "FPE:nPETSC ERROR: Floating Point Exception,probably divide by zero",
 30:     "KILL",
 31:     "BUS: nPETSC ERROR: Bus Error, possibly illegal memory access",
 32:     "SEGV:nPETSC ERROR: Segmentation Violation, probably memory access out of range",
 33:     "SYS",
 34:     "PIPE",
 35:     "ALRM",
 36:     "TERM",
 37:     "URG",
 38:     "STOP",
 39:     "TSTP",
 40:     "CONT",
 41:     "CHLD" };


 44: EXTERN_C_BEGIN
 45: /*
 46:     PetscSignalHandler_Private - This is the signal handler called by the system. This calls 
 47:              any signal handler set by PETSc or the application code.
 48:  
 49:    Input Parameters: (depends on system)
 50: .    sig - integer code indicating the type of signal
 51: .    code - ??
 52: .    sigcontext - ??
 53: .    addr - ??

 55:     Note: this is declared extern "C" because it is passed to the system routine signal()
 56:           which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be
 57:           extern "C".

 59: */
 60: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
 61: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
 62: #else
 63: static void PetscSignalHandler_Private(int sig)
 64: #endif
 65: {

 69:   if (!sh || !sh->handler) {
 70:     PetscDefaultSignalHandler(sig,(void*)0);
 71:   } else{
 72:     (*sh->handler)(sig,sh->ctx);
 73:   }
 74:   if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
 75: }
 76: EXTERN_C_END

 78: /*@
 79:    PetscDefaultSignalHandler - Default signal handler.

 81:    Not Collective

 83:    Level: advanced

 85:    Input Parameters:
 86: +  sig - signal value
 87: -  ptr - unused pointer

 89:    Concepts: signal handler^default

 91: @*/
 92: int PetscDefaultSignalHandler(int sig,void *ptr)
 93: {
 94:   int         ierr;
 95:   static char buf[1024];

 98:   signal(sig,SIG_DFL);
 99:   if (sig >= 0 && sig <= 20) {
100:     sprintf(buf,"Caught signal %sn",SIGNAME[sig]);
101:   } else {
102:     PetscStrcpy(buf,"Caught signaln");
103:   }
104:   PetscStrcat(buf,"PETSC ERROR: Try option -start_in_debugger or ");
105:   PetscStrcat(buf,"-on_error_attach_debugger ");
106:   PetscStrcat(buf,"tonPETSC ERROR: determine where problem occursn");
107: #if defined(PETSC_USE_STACK)
108:   if (!PetscStackActive) {
109:     PetscStrcat(buf,"PETSC ERROR: or try option -log_stackn");
110:   } else {
111:     PetscStackPop;  /* remove stack frames for error handlers */
112:     PetscStackPop;
113:     PetscStrcat(buf,"PETSC ERROR: likely location of problem given above in stackn");
114:     (*PetscErrorPrintf)("--------------- Stack Frames ---------------n");
115:     PetscStackView(PETSC_VIEWER_STDOUT_WORLD);
116:     (*PetscErrorPrintf)("--------------------------------------------n");
117:   }
118: #endif
119:    PetscError(0,"unknownfunction","unknown file"," ",PETSC_ERR_SIG,0,buf);
120:   MPI_Abort(PETSC_COMM_WORLD,ierr);
121:   return(0);
122: }

124: #if !defined(PETSC_SIGNAL_CAST)
125: #define PETSC_SIGNAL_CAST
126: #endif

128: /*@C
129:    PetscPushSignalHandler - Catches the usual fatal errors and 
130:    calls a user-provided routine.

132:    Not Collective

134:     Input Parameter:
135: +  routine - routine to call when a signal is received
136: -  ctx - optional context needed by the routine

138:   Level: developer

140:    Concepts: signal handler^setting

142: @*/
143: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
144: {
145:   struct  SH *newsh;
146:   int        ierr;

149:   if (!SignalSet && routine) {
150:     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
151:     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
152:     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
153: #if !defined(PETSC_MISSING_SIGSYS)
154:     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
155: #endif
156: #if !defined(PETSC_MISSING_SIGBUS)
157:     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
158: #endif
159: #if !defined(PETSC_MISSING_SIGQUIT)
160:     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
161: #endif
162:     SignalSet = PETSC_TRUE;
163:   }
164:   if (!routine) {
165:     signal(SIGILL,  0);
166:     signal(SIGFPE,  0);
167:     signal(SIGSEGV, 0);
168: #if !defined(PETSC_MISSING_SIGSYS)
169:     signal(SIGSYS,  0);
170: #endif
171: #if !defined(PETSC_MISSING_SIGBUS)
172:     signal(SIGBUS,  0);
173: #endif
174: #if !defined(PETSC_MISSING_SIGQUIT)
175:     signal(SIGQUIT, 0);
176: #endif
177:     SignalSet = PETSC_FALSE;
178:   }
179:   PetscNew(struct SH,&newsh);
180:   if (sh) {newsh->previous = sh;}
181:   else {newsh->previous = 0;}
182:   newsh->handler = routine;
183:   newsh->ctx     = ctx;
184:   sh             = newsh;
185:   return(0);
186: }

188: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
189: int PetscPopSignalHandler(void)
190: {
191:   struct SH *tmp;

194:   if (!sh) return(0);
195:   tmp = sh;
196:   sh  = sh->previous;
197:   PetscFree(tmp);
198:   if (!sh || !sh->handler) {
199:     signal(SIGILL,  0);
200:     signal(SIGFPE,  0);
201:     signal(SIGSEGV, 0);
202: #if !defined(PETSC_MISSING_SIGSYS)
203:     signal(SIGSYS,  0);
204: #endif
205: #if !defined(PETSC_MISSING_SIGBUS)
206:     signal(SIGBUS,  0);
207: #endif
208: #if !defined(PETSC_MISSING_SIGQUIT)
209:     signal(SIGQUIT, 0);
210: #endif
211:     SignalSet = PETSC_FALSE;
212:   } else {
213:     SignalSet = PETSC_TRUE;
214:   }
215:   return(0);
216: }