Actual source code: signal.c

  1: /*$Id: signal.c,v 1.80 2001/04/23 15:47:54 bsmith 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: #undef __FUNCT__  
 47: /*
 48:     PetscSignalHandler_Private - This is the signal handler called by the system. This calls 
 49:              any signal handler set by PETSc or the application code.
 50:  
 51:    Input Parameters: (depends on system)
 52: .    sig - integer code indicating the type of signal
 53: .    code - ??
 54: .    sigcontext - ??
 55: .    addr - ??

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

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

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

 80: #undef __FUNCT__  
 82: /*@
 83:    PetscDefaultSignalHandler - Default signal handler.

 85:    Not Collective

 87:    Level: advanced

 89:    Input Parameters:
 90: +  sig - signal value
 91: -  ptr - unused pointer

 93:    Concepts: signal handler^default

 95: @*/
 96: int PetscDefaultSignalHandler(int sig,void *ptr)
 97: {
 98:   int         ierr;
 99:   static char buf[1024];

102:   signal(sig,SIG_DFL);
103:   if (sig >= 0 && sig <= 20) {
104:     sprintf(buf,"Caught signal %sn",SIGNAME[sig]);
105:   } else {
106:     PetscStrcpy(buf,"Caught signaln");
107:   }
108:   PetscStrcat(buf,"PETSC ERROR: Try option -start_in_debugger or ");
109:   PetscStrcat(buf,"-on_error_attach_debugger ");
110:   PetscStrcat(buf,"tonPETSC ERROR: determine where problem occursn");
111: #if defined(PETSC_USE_STACK)
112:   if (!PetscStackActive) {
113:     PetscStrcat(buf,"PETSC ERROR: or try option -log_stackn");
114:   } else {
115:     PetscStackPop;  /* remove stack frames for error handlers */
116:     PetscStackPop;
117:     PetscStrcat(buf,"PETSC ERROR: likely location of problem given above in stackn");
118:     (*PetscErrorPrintf)("--------------- Stack Frames ---------------n");
119:     PetscStackView(PETSC_VIEWER_STDOUT_WORLD);
120:     (*PetscErrorPrintf)("--------------------------------------------n");
121:   }
122: #endif
123: #if !defined(PETSC_USE_BOPT_g)
124:   PetscStrcat(buf,"PETSC ERROR: compile, link, and run with BOPT=g or g_c++ or g_complexn");
125:   PetscStrcat(buf,"PETSC ERROR: to get more information on the crash.n");
126: #endif
127:    PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_SIG,1,buf);
128:   MPI_Abort(PETSC_COMM_WORLD,ierr);
129:   return(0);
130: }

132: #if !defined(PETSC_SIGNAL_CAST)
133: #define PETSC_SIGNAL_CAST
134: #endif

136: #undef __FUNCT__  
138: /*@C
139:    PetscPushSignalHandler - Catches the usual fatal errors and 
140:    calls a user-provided routine.

142:    Not Collective

144:     Input Parameter:
145: +  routine - routine to call when a signal is received
146: -  ctx - optional context needed by the routine

148:   Level: developer

150:    Concepts: signal handler^setting

152: @*/
153: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
154: {
155:   struct  SH *newsh;
156:   int        ierr;

159:   if (!SignalSet && routine) {
160:     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
161:     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
162:     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
163: #if !defined(PETSC_MISSING_SIGSYS)
164:     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
165: #endif
166: #if !defined(PETSC_MISSING_SIGBUS)
167:     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
168: #endif
169: #if !defined(PETSC_MISSING_SIGQUIT)
170:     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
171: #endif
172:     SignalSet = PETSC_TRUE;
173:   }
174:   if (!routine) {
175:     signal(SIGILL,  0);
176:     signal(SIGFPE,  0);
177:     signal(SIGSEGV, 0);
178: #if !defined(PETSC_MISSING_SIGSYS)
179:     signal(SIGSYS,  0);
180: #endif
181: #if !defined(PETSC_MISSING_SIGBUS)
182:     signal(SIGBUS,  0);
183: #endif
184: #if !defined(PETSC_MISSING_SIGQUIT)
185:     signal(SIGQUIT, 0);
186: #endif
187:     SignalSet = PETSC_FALSE;
188:   }
189:   PetscNew(struct SH,&newsh);
190:   if (sh) {newsh->previous = sh;}
191:   else {newsh->previous = 0;}
192:   newsh->handler = routine;
193:   newsh->ctx     = ctx;
194:   sh             = newsh;
195:   return(0);
196: }

198: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
199: #undef __FUNCT__  
201: int PetscPopSignalHandler(void)
202: {
203:   struct SH *tmp;

206:   if (!sh) return(0);
207:   tmp = sh;
208:   sh  = sh->previous;
209:   PetscFree(tmp);
210:   if (!sh || !sh->handler) {
211:     signal(SIGILL,  0);
212:     signal(SIGFPE,  0);
213:     signal(SIGSEGV, 0);
214: #if !defined(PETSC_MISSING_SIGSYS)
215:     signal(SIGSYS,  0);
216: #endif
217: #if !defined(PETSC_MISSING_SIGBUS)
218:     signal(SIGBUS,  0);
219: #endif
220: #if !defined(PETSC_MISSING_SIGQUIT)
221:     signal(SIGQUIT, 0);
222: #endif
223:     SignalSet = PETSC_FALSE;
224:   } else {
225:     SignalSet = PETSC_TRUE;
226:   }
227:   return(0);
228: }