Actual source code: signal.c


  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: {

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

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

 59:    Not Collective

 61:    Level: advanced

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

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

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

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

141:   (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
142:   (*PetscErrorPrintf)("or see https://petsc.org/release/faq/#valgrind\n");
143:   (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple MacOS to find memory corruption errors\n");
144: #if defined(PETSC_HAVE_CUDA)
145:   (*PetscErrorPrintf)("or try https://docs.nvidia.com/cuda/cuda-memcheck/index.html on NVIDIA CUDA systems to find memory corruption errors\n");
146: #endif
147: #if PetscDefined(USE_DEBUG)
148:   PetscStackPop;  /* remove stack frames for error handlers */
149:   PetscStackPop;
150:   (*PetscErrorPrintf)("likely location of problem given in stack below\n");
151:   (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
152:   PetscStackView(PETSC_STDOUT);
153: #else
154:   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
155:   (*PetscErrorPrintf)("to get more information on the crash.\n");
156: #endif
157:   PetscError(PETSC_COMM_SELF,0,"User provided function","unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
158: #if !defined(PETSC_MISSING_SIGBUS)
159:   if (sig == SIGSEGV || sig == SIGBUS) {
160: #else
161:   if (sig == SIGSEGV) {
162: #endif
163:     PetscBool debug;

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

178: #if !defined(PETSC_SIGNAL_CAST)
179: #define PETSC_SIGNAL_CAST
180: #endif

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

186:    Not Collective

188:    Input Parameters:
189: +  routine - routine to call when a signal is received
190: -  ctx - optional context needed by the routine

192:   Level: developer

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

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

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

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

342:    Not Collective

344:   Level: developer

346: .seealso: PetscPushSignalHandler()

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

353:   if (!sh) return 0;

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