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: /*
 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: #if !defined(PETSC_USE_BOPT_g)
120:   PetscStrcat(buf,"PETSC ERROR: compile, link, and run with BOPT=g or g_c++ or g_complexn");
121:   PetscStrcat(buf,"PETSC ERROR: to get more information on the crash.n");
122: #endif
123:    PetscError(0,"unknownfunction","Unknown file","Unknown directory",PETSC_ERR_SIG,1,buf);
124:   MPI_Abort(PETSC_COMM_WORLD,ierr);
125:   return(0);
126: }

128: #if !defined(PETSC_SIGNAL_CAST)
129: #define PETSC_SIGNAL_CAST
130: #endif

132: /*@C
133:    PetscPushSignalHandler - Catches the usual fatal errors and 
134:    calls a user-provided routine.

136:    Not Collective

138:     Input Parameter:
139: +  routine - routine to call when a signal is received
140: -  ctx - optional context needed by the routine

142:   Level: developer

144:    Concepts: signal handler^setting

146: @*/
147: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
148: {
149:   struct  SH *newsh;
150:   int        ierr;

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

192: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
193: int PetscPopSignalHandler(void)
194: {
195:   struct SH *tmp;

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