Actual source code: signal.c

petsc-3.14.6 2021-03-30
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>
  8: #include <stdlib.h> /* for _Exit() */

 10: static PetscClassId SIGNAL_CLASSID = 0;

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

 21: /* Called by MPI_Abort() to suppress user-registered atexit()/on_exit() functions.
 22:    See discussion at https://gitlab.com/petsc/petsc/-/merge_requests/2745.
 23: */
 24: static void MyExit(void)
 25: {
 26:   _Exit(MPI_ERR_OTHER);
 27: }

 29: /*
 30:     PetscSignalHandler_Private - This is the signal handler called by the system. This calls
 31:              any signal handler set by PETSc or the application code.

 33:    Input Parameters: (depends on system)
 34: .    sig - integer code indicating the type of signal
 35: .    code - ??
 36: .    sigcontext - ??
 37: .    addr - ??

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

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

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

 60:    Not Collective

 62:    Level: advanced

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

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

 75:   if (sig == SIGSEGV) PetscSignalSegvCheckPointerOrMpi();
 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 https://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
145:   (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
146:   if (PetscDefined(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:   } else {
156:     (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
157:     (*PetscErrorPrintf)("to get more information on the crash.\n");
158:   }
159:    PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
160: #if !defined(PETSC_MISSING_SIGBUS)
161:   if (sig == SIGSEGV || sig == SIGBUS) {
162: #else
163:   if (sig == SIGSEGV) {
164: #endif
165:     PetscBool debug;

167:     PetscMallocGetDebug(&debug,NULL,NULL);
168:     if (debug) {
169:       (*PetscErrorPrintf)("Checking the memory for corruption.\n");
170:       PetscMallocValidate(__LINE__,PETSC_FUNCTION_NAME,__FILE__);
171:     } else {
172:       (*PetscErrorPrintf)("Run with -malloc_debug to check if memory corruption is causing the crash.\n");
173:     }
174:   }
175:   atexit(MyExit);
176:   PETSCABORT(PETSC_COMM_WORLD,(int)ierr);
177:   return(0);
178: }

180: #if !defined(PETSC_SIGNAL_CAST)
181: #define PETSC_SIGNAL_CAST
182: #endif

184: /*@C
185:    PetscPushSignalHandler - Catches the usual fatal errors and
186:    calls a user-provided routine.

188:    Not Collective

190:     Input Parameter:
191: +  routine - routine to call when a signal is received
192: -  ctx - optional context needed by the routine

194:   Level: developer

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

198: @*/
199: PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
200: {
201:   struct  SH     *newsh;

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

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

343:    Not Collective

345:   Level: developer

347: .seealso: PetscPushSignalHandler()

349: @*/
350: PetscErrorCode  PetscPopSignalHandler(void)
351: {
352:   struct SH      *tmp;

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

359:   tmp = sh;
360:   sh  = sh->previous;
361:   PetscFree(tmp);
362:   if (!sh || !sh->handler) {
363: #if !defined(PETSC_MISSING_SIGALRM)
364:     /* signal(SIGALRM, SIG_DFL); */
365: #endif
366: #if !defined(PETSC_MISSING_SIGBUS)
367:     signal(SIGBUS,  SIG_DFL);
368: #endif
369: #if !defined(PETSC_MISSING_SIGCONT)
370:     /* signal(SIGCONT, SIG_DFL); */
371: #endif
372: #if !defined(PETSC_MISSING_SIGFPE)
373:     signal(SIGFPE,  SIG_DFL);
374: #endif
375: #if !defined(PETSC_MISSING_SIGHUP)
376:     signal(SIGHUP,  SIG_DFL);
377: #endif
378: #if !defined(PETSC_MISSING_SIGILL)
379:     signal(SIGILL,  SIG_DFL);
380: #endif
381: #if !defined(PETSC_MISSING_SIGINT)
382:     /* signal(SIGINT,  SIG_DFL); */
383: #endif
384: #if !defined(PETSC_MISSING_SIGPIPE)
385:     signal(SIGPIPE, SIG_DFL);
386: #endif
387: #if !defined(PETSC_MISSING_SIGQUIT)
388:     signal(SIGQUIT, SIG_DFL);
389: #endif
390: #if !defined(PETSC_MISSING_SIGSEGV)
391:     signal(SIGSEGV, SIG_DFL);
392: #endif
393: #if !defined(PETSC_MISSING_SIGSYS)
394:     signal(SIGSYS,  SIG_DFL);
395: #endif
396: #if !defined(PETSC_MISSING_SIGTERM)
397:     signal(SIGTERM, SIG_DFL);
398: #endif
399: #if !defined(PETSC_MISSING_SIGTRAP)
400:     signal(SIGTRAP, SIG_DFL);
401: #endif
402: #if !defined(PETSC_MISSING_SIGTSTP)
403:     /* signal(SIGTSTP, SIG_DFL); */
404: #endif
405: #if !defined(PETSC_MISSING_SIGURG)
406:     signal(SIGURG,  SIG_DFL);
407: #endif
408: #if !defined(PETSC_MISSING_SIGUSR1)
409:     /* signal(SIGUSR1, SIG_DFL); */
410: #endif
411: #if !defined(PETSC_MISSING_SIGUSR2)
412:     /* signal(SIGUSR2, SIG_DFL); */
413: #endif
414:     SignalSet = PETSC_FALSE;
415:   } else {
416:     SignalSet = PETSC_TRUE;
417:   }
418:   return(0);
419: }