Actual source code: signal.c

petsc-3.4.5 2014-06-29
  2: /*
  3:       Routines to handle signals the program will receive.
  4:     Usually this will call the error handlers.
  5: */
  6: #include <petsc-private/petscimpl.h>             /*I   "petscsys.h"   I*/
  7: #include <signal.h>

  9: static PetscClassId SIGNAL_CLASSID = 0;

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

 22: /*
 23:     PetscSignalHandler_Private - This is the signal handler called by the system. This calls
 24:              any signal handler set by PETSc or the application code.

 26:    Input Parameters: (depends on system)
 27: .    sig - integer code indicating the type of signal
 28: .    code - ??
 29: .    sigcontext - ??
 30: .    addr - ??

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

 36: */
 37: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
 38: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
 39: #else
 40: static void PetscSignalHandler_Private(int sig)
 41: #endif
 42: {

 46:   if (!sh || !sh->handler) PetscSignalHandlerDefault(sig,(void*)0);
 47:   else {
 48:     if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
 49:     (*sh->handler)(sig,sh->ctx);
 50:   }
 51:   if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
 52: }

 56: /*@
 57:    PetscSignalHandlerDefault - Default signal handler.

 59:    Not Collective

 61:    Level: advanced

 63:    Input Parameters:
 64: +  sig - signal value
 65: -  ptr - unused pointer

 67:    Concepts: signal handler^default

 69: @*/
 70: PetscErrorCode  PetscSignalHandlerDefault(int sig,void *ptr)
 71: {
 73:   const char     *SIGNAME[64];

 76:   SIGNAME[0]       = "Unknown signal";
 77: #if !defined(PETSC_MISSING_SIGABRT)
 78:   SIGNAME[SIGABRT] = "Abort";
 79: #endif
 80: #if !defined(PETSC_MISSING_SIGALRM)
 81:   SIGNAME[SIGALRM] = "Alarm";
 82: #endif
 83: #if !defined(PETSC_MISSING_SIGBUS)
 84:   SIGNAME[SIGBUS]  = "BUS: Bus Error, possibly illegal memory access";
 85: #endif
 86: #if !defined(PETSC_MISSING_SIGCHLD)
 87:   SIGNAME[SIGCHLD] = "CHLD";
 88: #endif
 89: #if !defined(PETSC_MISSING_SIGCONT)
 90:   SIGNAME[SIGCONT] = "CONT";
 91: #endif
 92: #if !defined(PETSC_MISSING_SIGFPE)
 93:   SIGNAME[SIGFPE]  = "FPE: Floating Point Exception,probably divide by zero";
 94: #endif
 95: #if !defined(PETSC_MISSING_SIGHUP)
 96:   SIGNAME[SIGHUP]  = "Hang up: Some other process (or the batch system) has told this process to end";
 97: #endif
 98: #if !defined(PETSC_MISSING_SIGILL)
 99:   SIGNAME[SIGILL]  = "Illegal instruction: Likely due to memory corruption";
100: #endif
101: #if !defined(PETSC_MISSING_SIGINT)
102:   SIGNAME[SIGINT]  = "Interrupt";
103: #endif
104: #if !defined(PETSC_MISSING_SIGKILL)
105:   SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
106: #endif
107: #if !defined(PETSC_MISSING_SIGPIPE)
108:   SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
109: #endif
110: #if !defined(PETSC_MISSING_SIGQUIT)
111:   SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
112: #endif
113: #if !defined(PETSC_MISSING_SIGSEGV)
114:   SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
115: #endif
116: #if !defined(PETSC_MISSING_SIGSYS)
117:   SIGNAME[SIGSYS]  = "SYS";
118: #endif
119: #if !defined(PETSC_MISSING_SIGTERM)
120:   SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end";
121: #endif
122: #if !defined(PETSC_MISSING_SIGTRAP)
123:   SIGNAME[SIGTRAP] = "TRAP";
124: #endif
125: #if !defined(PETSC_MISSING_SIGTSTP)
126:   SIGNAME[SIGTSTP] = "TSTP";
127: #endif
128: #if !defined(PETSC_MISSING_SIGURG)
129:   SIGNAME[SIGURG]  = "URG";
130: #endif
131: #if !defined(PETSC_MISSING_SIGUSR1)
132:   SIGNAME[SIGUSR1] = "User 1";
133: #endif
134: #if !defined(PETSC_MISSING_SIGUSR2)
135:   SIGNAME[SIGUSR2] = "User 2";
136: #endif

138:   signal(sig,SIG_DFL);
139:   (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
140:   if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
141:   else (*PetscErrorPrintf)("Caught signal\n");

143:   (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
144:   (*PetscErrorPrintf)("or see http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind");
145:   (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
146: #if defined(PETSC_USE_DEBUG)
147:   if (!PetscStackActive()) (*PetscErrorPrintf)("  or try option -log_stack\n");
148:   else {
149:     PetscStackPop;  /* remove stack frames for error handlers */
150:     PetscStackPop;
151:     (*PetscErrorPrintf)("likely location of problem given in stack below\n");
152:     (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
153:     PetscStackView(PETSC_STDOUT);
154:   }
155: #endif
156: #if !defined(PETSC_USE_DEBUG)
157:   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
158:   (*PetscErrorPrintf)("to get more information on the crash.\n");
159: #endif
160:    PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file","unknown directory",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
161:   MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
162:   return(0);
163: }

165: #if !defined(PETSC_SIGNAL_CAST)
166: #define PETSC_SIGNAL_CAST
167: #endif

171: /*@C
172:    PetscPushSignalHandler - Catches the usual fatal errors and
173:    calls a user-provided routine.

175:    Not Collective

177:     Input Parameter:
178: +  routine - routine to call when a signal is received
179: -  ctx - optional context needed by the routine

181:   Level: developer

183:    Concepts: signal handler^setting

185: .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()

187: @*/
188: PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
189: {
190:   struct  SH     *newsh;

194:   if (!SIGNAL_CLASSID) {
195:     /* PetscClassIdRegister("Signal",&SIGNAL_CLASSID); */
196:     SIGNAL_CLASSID = 19;
197:   }
198:   if (!SignalSet && routine) {
199:     /* Do not catch ABRT, CHLD, KILL */
200: #if !defined(PETSC_MISSING_SIGALRM)
201:     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
202: #endif
203: #if !defined(PETSC_MISSING_SIGBUS)
204:     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
205: #endif
206: #if !defined(PETSC_MISSING_SIGCONT)
207:     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
208: #endif
209: #if !defined(PETSC_MISSING_SIGFPE)
210:     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
211: #endif
212: #if !defined(PETSC_MISSING_SIGHUP)
213:     signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
214: #endif
215: #if !defined(PETSC_MISSING_SIGILL)
216:     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
217: #endif
218: #if !defined(PETSC_MISSING_SIGINT)
219:     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
220: #endif
221: #if !defined(PETSC_MISSING_SIGPIPE)
222:     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
223: #endif
224: #if !defined(PETSC_MISSING_SIGQUIT)
225:     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
226: #endif
227: #if !defined(PETSC_MISSING_SIGSEGV)
228:     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
229: #endif
230: #if !defined(PETSC_MISSING_SIGSYS)
231:     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
232: #endif
233: #if !defined(PETSC_MISSING_SIGTERM)
234:     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
235: #endif
236: #if !defined(PETSC_MISSING_SIGTRAP)
237:     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
238: #endif
239: #if !defined(PETSC_MISSING_SIGTSTP)
240:     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
241: #endif
242: #if !defined(PETSC_MISSING_SIGURG)
243:     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
244: #endif
245: #if !defined(PETSC_MISSING_SIGUSR1)
246:     /*    signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
247: #endif
248: #if !defined(PETSC_MISSING_SIGUSR2)
249:     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
250: #endif
251:     SignalSet = PETSC_TRUE;
252:   }
253:   if (!routine) {
254: #if !defined(PETSC_MISSING_SIGALRM)
255:     /* signal(SIGALRM, 0); */
256: #endif
257: #if !defined(PETSC_MISSING_SIGBUS)
258:     signal(SIGBUS,  0);
259: #endif
260: #if !defined(PETSC_MISSING_SIGCONT)
261:     /* signal(SIGCONT, 0); */
262: #endif
263: #if !defined(PETSC_MISSING_SIGFPE)
264:     signal(SIGFPE,  0);
265: #endif
266: #if !defined(PETSC_MISSING_SIGHUP)
267:     signal(SIGHUP,  0);
268: #endif
269: #if !defined(PETSC_MISSING_SIGILL)
270:     signal(SIGILL,  0);
271: #endif
272: #if !defined(PETSC_MISSING_SIGINT)
273:     /* signal(SIGINT,  0); */
274: #endif
275: #if !defined(PETSC_MISSING_SIGPIPE)
276:     signal(SIGPIPE, 0);
277: #endif
278: #if !defined(PETSC_MISSING_SIGQUIT)
279:     signal(SIGQUIT, 0);
280: #endif
281: #if !defined(PETSC_MISSING_SIGSEGV)
282:     signal(SIGSEGV, 0);
283: #endif
284: #if !defined(PETSC_MISSING_SIGSYS)
285:     signal(SIGSYS,  0);
286: #endif
287: #if !defined(PETSC_MISSING_SIGTERM)
288:     signal(SIGTERM, 0);
289: #endif
290: #if !defined(PETSC_MISSING_SIGTRAP)
291:     signal(SIGTRAP, 0);
292: #endif
293: #if !defined(PETSC_MISSING_SIGTSTP)
294:     /* signal(SIGTSTP, 0); */
295: #endif
296: #if !defined(PETSC_MISSING_SIGURG)
297:     signal(SIGURG,  0);
298: #endif
299: #if !defined(PETSC_MISSING_SIGUSR1)
300:     /*    signal(SIGUSR1, 0); */
301: #endif
302: #if !defined(PETSC_MISSING_SIGUSR2)
303:     /* signal(SIGUSR2, 0); */
304: #endif
305:     SignalSet = PETSC_FALSE;
306:   }
307:   PetscNew(struct SH,&newsh);
308:   if (sh) {
309:     if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
310:     newsh->previous = sh;
311:   }  else newsh->previous = 0;
312:   newsh->handler = routine;
313:   newsh->ctx     = ctx;
314:   newsh->classid = SIGNAL_CLASSID;
315:   sh             = newsh;
316:   return(0);
317: }

321: /*@
322:    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
323:        If no signal handlers are left on the stack it will remove the PETSc signal handler.
324:        (That is PETSc will no longer catch signals).

326:    Not Collective

328:   Level: developer

330:    Concepts: signal handler^setting

332: .seealso: PetscPushSignalHandler()

334: @*/
335: PetscErrorCode  PetscPopSignalHandler(void)
336: {
337:   struct SH *tmp;

340:   if (!sh) return(0);
341:   if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");

343:   tmp = sh;
344:   sh  = sh->previous;
345:   PetscFreeVoid(tmp);
346:   if (!sh || !sh->handler) {
347: #if !defined(PETSC_MISSING_SIGALRM)
348:     /* signal(SIGALRM, 0); */
349: #endif
350: #if !defined(PETSC_MISSING_SIGBUS)
351:     signal(SIGBUS,  0);
352: #endif
353: #if !defined(PETSC_MISSING_SIGCONT)
354:     /* signal(SIGCONT, 0); */
355: #endif
356: #if !defined(PETSC_MISSING_SIGFPE)
357:     signal(SIGFPE,  0);
358: #endif
359: #if !defined(PETSC_MISSING_SIGHUP)
360:     signal(SIGHUP,  0);
361: #endif
362: #if !defined(PETSC_MISSING_SIGILL)
363:     signal(SIGILL,  0);
364: #endif
365: #if !defined(PETSC_MISSING_SIGINT)
366:     /* signal(SIGINT,  0); */
367: #endif
368: #if !defined(PETSC_MISSING_SIGPIPE)
369:     signal(SIGPIPE, 0);
370: #endif
371: #if !defined(PETSC_MISSING_SIGQUIT)
372:     signal(SIGQUIT, 0);
373: #endif
374: #if !defined(PETSC_MISSING_SIGSEGV)
375:     signal(SIGSEGV, 0);
376: #endif
377: #if !defined(PETSC_MISSING_SIGSYS)
378:     signal(SIGSYS,  0);
379: #endif
380: #if !defined(PETSC_MISSING_SIGTERM)
381:     signal(SIGTERM, 0);
382: #endif
383: #if !defined(PETSC_MISSING_SIGTRAP)
384:     signal(SIGTRAP, 0);
385: #endif
386: #if !defined(PETSC_MISSING_SIGTSTP)
387:     /* signal(SIGTSTP, 0); */
388: #endif
389: #if !defined(PETSC_MISSING_SIGURG)
390:     signal(SIGURG,  0);
391: #endif
392: #if !defined(PETSC_MISSING_SIGUSR1)
393:     /*    signal(SIGUSR1, 0); */
394: #endif
395: #if !defined(PETSC_MISSING_SIGUSR2)
396:     /* signal(SIGUSR2, 0); */
397: #endif
398:     SignalSet = PETSC_FALSE;
399:   } else {
400:     SignalSet = PETSC_TRUE;
401:   }
402:   return(0);
403: }


406: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_SIGINFO_T)
407: #include <setjmp.h>
408: PETSC_VISIBILITY_INTERNAL jmp_buf PetscSegvJumpBuf;
409: /*
410:     This routine is called if a segmentation violation, i.e. inaccessible memory access

413:     It simply unrolls the UNIX signal and returns to the location where setjump(PetscSeqvJumpBuf) is declared.
414: */
415: PETSC_INTERN void PetscSegv_sigaction(int signal, siginfo_t *si, void *arg)
416: {
417:   longjmp(PetscSegvJumpBuf,1);
418:   return;
419: }
420: #endif