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: {
46: PetscErrorCode ierr;
48: if (!sh || !sh->handler) ierr = 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: ierr = (*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: Input Parameters:
62: + sig - signal value
63: - ptr - unused pointer
65: Developer Note:
66: This does not call `PetscError()`, handles the entire error process directly
68: Level: advanced
70: @*/
71: PetscErrorCode PetscSignalHandlerDefault(int sig, void *ptr)
72: {
73: PetscErrorCode ierr;
74: const char *SIGNAME[64];
76: if (sig == SIGSEGV) PetscSignalSegvCheckPointerOrMpi();
77: SIGNAME[0] = "Unknown signal";
78: #if !defined(PETSC_MISSING_SIGABRT)
79: SIGNAME[SIGABRT] = "Abort";
80: #endif
81: #if !defined(PETSC_MISSING_SIGALRM)
82: SIGNAME[SIGALRM] = "Alarm";
83: #endif
84: #if !defined(PETSC_MISSING_SIGBUS)
85: SIGNAME[SIGBUS] = "BUS: Bus Error, possibly illegal memory access";
86: #endif
87: #if !defined(PETSC_MISSING_SIGCHLD)
88: SIGNAME[SIGCHLD] = "CHLD";
89: #endif
90: #if !defined(PETSC_MISSING_SIGCONT)
91: SIGNAME[SIGCONT] = "CONT";
92: #endif
93: #if !defined(PETSC_MISSING_SIGFPE)
94: SIGNAME[SIGFPE] = "FPE: Floating Point Exception,probably divide by zero";
95: #endif
96: #if !defined(PETSC_MISSING_SIGHUP)
97: SIGNAME[SIGHUP] = "Hang up: Some other process (or the batch system) has told this process to end";
98: #endif
99: #if !defined(PETSC_MISSING_SIGILL)
100: SIGNAME[SIGILL] = "Illegal instruction: Likely due to memory corruption";
101: #endif
102: #if !defined(PETSC_MISSING_SIGINT)
103: SIGNAME[SIGINT] = "Interrupt";
104: #endif
105: #if !defined(PETSC_MISSING_SIGKILL)
106: SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
107: #endif
108: #if !defined(PETSC_MISSING_SIGPIPE)
109: SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
110: #endif
111: #if !defined(PETSC_MISSING_SIGQUIT)
112: SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
113: #endif
114: #if !defined(PETSC_MISSING_SIGSEGV)
115: SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
116: #endif
117: #if !defined(PETSC_MISSING_SIGSYS)
118: SIGNAME[SIGSYS] = "SYS";
119: #endif
120: #if !defined(PETSC_MISSING_SIGTERM)
121: SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end";
122: #endif
123: #if !defined(PETSC_MISSING_SIGTRAP)
124: SIGNAME[SIGTRAP] = "TRAP";
125: #endif
126: #if !defined(PETSC_MISSING_SIGTSTP)
127: SIGNAME[SIGTSTP] = "TSTP";
128: #endif
129: #if !defined(PETSC_MISSING_SIGURG)
130: SIGNAME[SIGURG] = "URG";
131: #endif
132: #if !defined(PETSC_MISSING_SIGUSR1)
133: SIGNAME[SIGUSR1] = "User 1";
134: #endif
135: #if !defined(PETSC_MISSING_SIGUSR2)
136: SIGNAME[SIGUSR2] = "User 2";
137: #endif
139: signal(sig, SIG_DFL);
140: ierr = PetscSleep(PetscGlobalRank % 4); /* prevent some jumbling of error messages from different ranks */
141: ierr = (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
142: if (sig >= 0 && sig <= 20) ierr = (*PetscErrorPrintf)("Caught signal number %d %s\n", sig, SIGNAME[sig]);
143: else ierr = (*PetscErrorPrintf)("Caught signal\n");
145: ierr = (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
146: ierr = (*PetscErrorPrintf)("or see https://petsc.org/release/faq/#valgrind and https://petsc.org/release/faq/\n");
147: #if defined(PETSC_HAVE_CUDA)
148: ierr = (*PetscErrorPrintf)("or try https://docs.nvidia.com/cuda/cuda-memcheck/index.html on NVIDIA CUDA systems to find memory corruption errors\n");
149: #endif
150: #if PetscDefined(USE_DEBUG)
151: #if !PetscDefined(HAVE_THREADSAFETY)
152: ierr = (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
153: ierr = PetscStackView(PETSC_STDOUT);
154: #endif
155: #else
156: ierr = (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
157: ierr = (*PetscErrorPrintf)("to get more information on the crash.\n");
158: #endif
159: #if !defined(PETSC_MISSING_SIGBUS)
160: if (sig == SIGSEGV || sig == SIGBUS) {
161: #else
162: if (sig == SIGSEGV) {
163: #endif
164: PetscBool debug;
166: ierr = PetscMallocGetDebug(&debug, NULL, NULL);
167: if (debug) ierr = PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__);
168: else ierr = (*PetscErrorPrintf)("Run with -malloc_debug to check if memory corruption is causing the crash.\n");
169: }
170: atexit(MyExit);
171: (void)ierr;
172: PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SIG);
173: return PETSC_SUCCESS;
174: }
176: #if !defined(PETSC_SIGNAL_CAST)
177: #define PETSC_SIGNAL_CAST
178: #endif
180: /*@C
181: PetscPushSignalHandler - Catches the usual fatal errors and
182: calls a user-provided routine.
184: Not Collective
186: Input Parameters:
187: + routine - routine to call when a signal is received
188: - ctx - optional context needed by the routine
190: Level: developer
192: .seealso: `PetscPopSignalHandler()`, `PetscSignalHandlerDefault()`, `PetscPushErrorHandler()`
193: @*/
194: PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int, void *), void *ctx)
195: {
196: struct SH *newsh;
198: PetscFunctionBegin;
199: if (!SIGNAL_CLASSID) {
200: /* PetscCall(PetscClassIdRegister("Signal",&SIGNAL_CLASSID)); */
201: SIGNAL_CLASSID = 19;
202: }
203: if (!SignalSet && routine) {
204: /* Do not catch ABRT, CHLD, KILL */
205: #if !defined(PETSC_MISSING_SIGALRM)
206: /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
207: #endif
208: #if !defined(PETSC_MISSING_SIGBUS)
209: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
210: #endif
211: #if !defined(PETSC_MISSING_SIGCONT)
212: /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
213: #endif
214: #if !defined(PETSC_MISSING_SIGFPE)
215: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
216: #endif
217: #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION)
218: {
219: struct sigaction action;
220: sigaction(SIGHUP, NULL, &action);
221: if (action.sa_handler == SIG_IGN) {
222: PetscCall(PetscInfo(NULL, "SIGHUP previously set to ignore, therefor not changing its signal handler\n"));
223: } else {
224: signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
225: }
226: }
227: #endif
228: #if !defined(PETSC_MISSING_SIGILL)
229: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
230: #endif
231: #if !defined(PETSC_MISSING_SIGINT)
232: /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
233: #endif
234: #if !defined(PETSC_MISSING_SIGPIPE)
235: signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
236: #endif
237: #if !defined(PETSC_MISSING_SIGQUIT)
238: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
239: #endif
240: #if !defined(PETSC_MISSING_SIGSEGV)
241: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
242: #endif
243: #if !defined(PETSC_MISSING_SIGSYS)
244: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
245: #endif
246: #if !defined(PETSC_MISSING_SIGTERM)
247: #if !defined(OMPI_MAJOR_VERSION)
248: /* OpenMPI may use SIGTERM to close down all its ranks; we don't want to generate many confusing PETSc error messages in that case */
249: signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
250: #endif
251: #endif
252: #if !defined(PETSC_MISSING_SIGTRAP)
253: signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
254: #endif
255: #if !defined(PETSC_MISSING_SIGTSTP)
256: /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
257: #endif
258: #if !defined(PETSC_MISSING_SIGURG)
259: signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
260: #endif
261: #if !defined(PETSC_MISSING_SIGUSR1)
262: /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
263: #endif
264: #if !defined(PETSC_MISSING_SIGUSR2)
265: /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
266: #endif
267: SignalSet = PETSC_TRUE;
268: }
269: if (!routine) {
270: #if !defined(PETSC_MISSING_SIGALRM)
271: /* signal(SIGALRM, SIG_DFL); */
272: #endif
273: #if !defined(PETSC_MISSING_SIGBUS)
274: signal(SIGBUS, SIG_DFL);
275: #endif
276: #if !defined(PETSC_MISSING_SIGCONT)
277: /* signal(SIGCONT, SIG_DFL); */
278: #endif
279: #if !defined(PETSC_MISSING_SIGFPE)
280: signal(SIGFPE, SIG_DFL);
281: #endif
282: #if !defined(PETSC_MISSING_SIGHUP)
283: signal(SIGHUP, SIG_DFL);
284: #endif
285: #if !defined(PETSC_MISSING_SIGILL)
286: signal(SIGILL, SIG_DFL);
287: #endif
288: #if !defined(PETSC_MISSING_SIGINT)
289: /* signal(SIGINT, SIG_DFL); */
290: #endif
291: #if !defined(PETSC_MISSING_SIGPIPE)
292: signal(SIGPIPE, SIG_DFL);
293: #endif
294: #if !defined(PETSC_MISSING_SIGQUIT)
295: signal(SIGQUIT, SIG_DFL);
296: #endif
297: #if !defined(PETSC_MISSING_SIGSEGV)
298: signal(SIGSEGV, SIG_DFL);
299: #endif
300: #if !defined(PETSC_MISSING_SIGSYS)
301: signal(SIGSYS, SIG_DFL);
302: #endif
303: #if !defined(PETSC_MISSING_SIGTERM)
304: signal(SIGTERM, SIG_DFL);
305: #endif
306: #if !defined(PETSC_MISSING_SIGTRAP)
307: signal(SIGTRAP, SIG_DFL);
308: #endif
309: #if !defined(PETSC_MISSING_SIGTSTP)
310: /* signal(SIGTSTP, SIG_DFL); */
311: #endif
312: #if !defined(PETSC_MISSING_SIGURG)
313: signal(SIGURG, SIG_DFL);
314: #endif
315: #if !defined(PETSC_MISSING_SIGUSR1)
316: /* signal(SIGUSR1, SIG_DFL); */
317: #endif
318: #if !defined(PETSC_MISSING_SIGUSR2)
319: /* signal(SIGUSR2, SIG_DFL); */
320: #endif
321: SignalSet = PETSC_FALSE;
322: }
323: PetscCall(PetscNew(&newsh));
324: if (sh) {
325: PetscCheck(sh->classid == SIGNAL_CLASSID, PETSC_COMM_SELF, PETSC_ERR_COR, "Signal object has been corrupted");
326: newsh->previous = sh;
327: } else newsh->previous = NULL;
328: newsh->handler = routine;
329: newsh->ctx = ctx;
330: newsh->classid = SIGNAL_CLASSID;
331: sh = newsh;
332: PetscFunctionReturn(PETSC_SUCCESS);
333: }
335: /*@
336: PetscPopSignalHandler - Removes the most last signal handler that was pushed.
337: If no signal handlers are left on the stack it will remove the PETSc signal handler.
338: (That is PETSc will no longer catch signals).
340: Not Collective
342: Level: developer
344: .seealso: `PetscPushSignalHandler()`
345: @*/
346: PetscErrorCode PetscPopSignalHandler(void)
347: {
348: struct SH *tmp;
350: PetscFunctionBegin;
351: if (!sh) PetscFunctionReturn(PETSC_SUCCESS);
352: PetscCheck(sh->classid == SIGNAL_CLASSID, PETSC_COMM_SELF, PETSC_ERR_COR, "Signal object has been corrupted");
354: tmp = sh;
355: sh = sh->previous;
356: PetscCall(PetscFree(tmp));
357: if (!sh || !sh->handler) {
358: #if !defined(PETSC_MISSING_SIGALRM)
359: /* signal(SIGALRM, SIG_DFL); */
360: #endif
361: #if !defined(PETSC_MISSING_SIGBUS)
362: signal(SIGBUS, SIG_DFL);
363: #endif
364: #if !defined(PETSC_MISSING_SIGCONT)
365: /* signal(SIGCONT, SIG_DFL); */
366: #endif
367: #if !defined(PETSC_MISSING_SIGFPE)
368: signal(SIGFPE, SIG_DFL);
369: #endif
370: #if !defined(PETSC_MISSING_SIGHUP)
371: signal(SIGHUP, SIG_DFL);
372: #endif
373: #if !defined(PETSC_MISSING_SIGILL)
374: signal(SIGILL, SIG_DFL);
375: #endif
376: #if !defined(PETSC_MISSING_SIGINT)
377: /* signal(SIGINT, SIG_DFL); */
378: #endif
379: #if !defined(PETSC_MISSING_SIGPIPE)
380: signal(SIGPIPE, SIG_DFL);
381: #endif
382: #if !defined(PETSC_MISSING_SIGQUIT)
383: signal(SIGQUIT, SIG_DFL);
384: #endif
385: #if !defined(PETSC_MISSING_SIGSEGV)
386: signal(SIGSEGV, SIG_DFL);
387: #endif
388: #if !defined(PETSC_MISSING_SIGSYS)
389: signal(SIGSYS, SIG_DFL);
390: #endif
391: #if !defined(PETSC_MISSING_SIGTERM)
392: signal(SIGTERM, SIG_DFL);
393: #endif
394: #if !defined(PETSC_MISSING_SIGTRAP)
395: signal(SIGTRAP, SIG_DFL);
396: #endif
397: #if !defined(PETSC_MISSING_SIGTSTP)
398: /* signal(SIGTSTP, SIG_DFL); */
399: #endif
400: #if !defined(PETSC_MISSING_SIGURG)
401: signal(SIGURG, SIG_DFL);
402: #endif
403: #if !defined(PETSC_MISSING_SIGUSR1)
404: /* signal(SIGUSR1, SIG_DFL); */
405: #endif
406: #if !defined(PETSC_MISSING_SIGUSR2)
407: /* signal(SIGUSR2, SIG_DFL); */
408: #endif
409: SignalSet = PETSC_FALSE;
410: } else {
411: SignalSet = PETSC_TRUE;
412: }
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }