Actual source code: signal.c

petsc-3.9.4 2018-09-11
Report Typos and Errors

  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>
  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;

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

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

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

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

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

 52: /*@
 53:    PetscSignalHandlerDefault - Default signal handler.

 55:    Not Collective

 57:    Level: advanced

 59:    Input Parameters:
 60: +  sig - signal value
 61: -  ptr - unused pointer

 63:    Concepts: signal handler^default

 65: @*/
 66: PetscErrorCode  PetscSignalHandlerDefault(int sig,void *ptr)
 67: {
 69:   const char     *SIGNAME[64];

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

134:   signal(sig,SIG_DFL);
135:   (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
136:   if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
137:   else (*PetscErrorPrintf)("Caught signal\n");

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

161: #if !defined(PETSC_SIGNAL_CAST)
162: #define PETSC_SIGNAL_CAST
163: #endif

165: /*@C
166:    PetscPushSignalHandler - Catches the usual fatal errors and
167:    calls a user-provided routine.

169:    Not Collective

171:     Input Parameter:
172: +  routine - routine to call when a signal is received
173: -  ctx - optional context needed by the routine

175:   Level: developer

177:    Concepts: signal handler^setting

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

181: @*/
182: PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
183: {
184:   struct  SH     *newsh;

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

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

318:    Not Collective

320:   Level: developer

322:    Concepts: signal handler^setting

324: .seealso: PetscPushSignalHandler()

326: @*/
327: PetscErrorCode  PetscPopSignalHandler(void)
328: {
329:   struct SH      *tmp;

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

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


399: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_SIGINFO_T)
400: #include <setjmp.h>
401: PETSC_VISIBILITY_INTERNAL jmp_buf PetscSegvJumpBuf;
402: /*
403:     This routine is called if a segmentation violation, i.e. inaccessible memory access

406:     It simply unrolls the UNIX signal and returns to the location where setjump(PetscSeqvJumpBuf) is declared.
407: */
408: PETSC_INTERN void PetscSegv_sigaction(int signal, siginfo_t *si, void *arg)
409: {
410:   longjmp(PetscSegvJumpBuf,1);
411:   return;
412: }
413: #endif