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: 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: 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: PetscSleep(PetscGlobalRank % 4); /* prevent some jumbling of error messages from different ranks */
140: (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
141: if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n", sig, SIGNAME[sig]);
142: else (*PetscErrorPrintf)("Caught signal\n");
144: (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
145: (*PetscErrorPrintf)("or see https://petsc.org/release/faq/#valgrind and https://petsc.org/release/faq/\n");
146: #if defined(PETSC_HAVE_CUDA)
147: (*PetscErrorPrintf)("or try https://docs.nvidia.com/cuda/cuda-memcheck/index.html on NVIDIA CUDA systems to find memory corruption errors\n");
148: #endif
149: #if PetscDefined(USE_DEBUG)
150: (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
151: PetscStackView(PETSC_STDOUT);
152: #else
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: #if !defined(PETSC_MISSING_SIGBUS)
157: if (sig == SIGSEGV || sig == SIGBUS) {
158: #else
159: if (sig == SIGSEGV) {
160: #endif
161: PetscBool debug;
163: PetscMallocGetDebug(&debug, NULL, NULL);
164: if (debug) PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__);
165: else (*PetscErrorPrintf)("Run with -malloc_debug to check if memory corruption is causing the crash.\n");
166: }
167: atexit(MyExit);
168: PETSCABORT(PETSC_COMM_WORLD, (int)PETSC_ERR_SIG);
169: return 0;
170: }
172: #if !defined(PETSC_SIGNAL_CAST)
173: #define PETSC_SIGNAL_CAST
174: #endif
176: /*@C
177: PetscPushSignalHandler - Catches the usual fatal errors and
178: calls a user-provided routine.
180: Not Collective
182: Input Parameters:
183: + routine - routine to call when a signal is received
184: - ctx - optional context needed by the routine
186: Level: developer
188: .seealso: `PetscPopSignalHandler()`, `PetscSignalHandlerDefault()`, `PetscPushErrorHandler()`
189: @*/
190: PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int, void *), void *ctx)
191: {
192: 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) && defined(PETSC_HAVE_STRUCT_SIGACTION)
213: {
214: struct sigaction action;
215: sigaction(SIGHUP, NULL, &action);
216: if (action.sa_handler == SIG_IGN) {
217: PetscInfo(NULL, "SIGHUP previously set to ignore, therefor not changing its signal handler\n");
218: } else {
219: signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
220: }
221: }
222: #endif
223: #if !defined(PETSC_MISSING_SIGILL)
224: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
225: #endif
226: #if !defined(PETSC_MISSING_SIGINT)
227: /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
228: #endif
229: #if !defined(PETSC_MISSING_SIGPIPE)
230: signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
231: #endif
232: #if !defined(PETSC_MISSING_SIGQUIT)
233: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
234: #endif
235: #if !defined(PETSC_MISSING_SIGSEGV)
236: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
237: #endif
238: #if !defined(PETSC_MISSING_SIGSYS)
239: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
240: #endif
241: #if !defined(PETSC_MISSING_SIGTERM)
242: #if !defined(OMPI_MAJOR_VERSION)
243: /* OpenMPI may use SIGTERM to close down all its ranks; we don't want to generate many confusing PETSc error messages in that case */
244: signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
245: #endif
246: #endif
247: #if !defined(PETSC_MISSING_SIGTRAP)
248: signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
249: #endif
250: #if !defined(PETSC_MISSING_SIGTSTP)
251: /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
252: #endif
253: #if !defined(PETSC_MISSING_SIGURG)
254: signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
255: #endif
256: #if !defined(PETSC_MISSING_SIGUSR1)
257: /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
258: #endif
259: #if !defined(PETSC_MISSING_SIGUSR2)
260: /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
261: #endif
262: SignalSet = PETSC_TRUE;
263: }
264: if (!routine) {
265: #if !defined(PETSC_MISSING_SIGALRM)
266: /* signal(SIGALRM, SIG_DFL); */
267: #endif
268: #if !defined(PETSC_MISSING_SIGBUS)
269: signal(SIGBUS, SIG_DFL);
270: #endif
271: #if !defined(PETSC_MISSING_SIGCONT)
272: /* signal(SIGCONT, SIG_DFL); */
273: #endif
274: #if !defined(PETSC_MISSING_SIGFPE)
275: signal(SIGFPE, SIG_DFL);
276: #endif
277: #if !defined(PETSC_MISSING_SIGHUP)
278: signal(SIGHUP, SIG_DFL);
279: #endif
280: #if !defined(PETSC_MISSING_SIGILL)
281: signal(SIGILL, SIG_DFL);
282: #endif
283: #if !defined(PETSC_MISSING_SIGINT)
284: /* signal(SIGINT, SIG_DFL); */
285: #endif
286: #if !defined(PETSC_MISSING_SIGPIPE)
287: signal(SIGPIPE, SIG_DFL);
288: #endif
289: #if !defined(PETSC_MISSING_SIGQUIT)
290: signal(SIGQUIT, SIG_DFL);
291: #endif
292: #if !defined(PETSC_MISSING_SIGSEGV)
293: signal(SIGSEGV, SIG_DFL);
294: #endif
295: #if !defined(PETSC_MISSING_SIGSYS)
296: signal(SIGSYS, SIG_DFL);
297: #endif
298: #if !defined(PETSC_MISSING_SIGTERM)
299: signal(SIGTERM, SIG_DFL);
300: #endif
301: #if !defined(PETSC_MISSING_SIGTRAP)
302: signal(SIGTRAP, SIG_DFL);
303: #endif
304: #if !defined(PETSC_MISSING_SIGTSTP)
305: /* signal(SIGTSTP, SIG_DFL); */
306: #endif
307: #if !defined(PETSC_MISSING_SIGURG)
308: signal(SIGURG, SIG_DFL);
309: #endif
310: #if !defined(PETSC_MISSING_SIGUSR1)
311: /* signal(SIGUSR1, SIG_DFL); */
312: #endif
313: #if !defined(PETSC_MISSING_SIGUSR2)
314: /* signal(SIGUSR2, SIG_DFL); */
315: #endif
316: SignalSet = PETSC_FALSE;
317: }
318: PetscNew(&newsh);
319: if (sh) {
321: newsh->previous = sh;
322: } else newsh->previous = NULL;
323: newsh->handler = routine;
324: newsh->ctx = ctx;
325: newsh->classid = SIGNAL_CLASSID;
326: sh = newsh;
327: return 0;
328: }
330: /*@
331: PetscPopSignalHandler - Removes the most last signal handler that was pushed.
332: If no signal handlers are left on the stack it will remove the PETSc signal handler.
333: (That is PETSc will no longer catch signals).
335: Not Collective
337: Level: developer
339: .seealso: `PetscPushSignalHandler()`
340: @*/
341: PetscErrorCode PetscPopSignalHandler(void)
342: {
343: struct SH *tmp;
345: if (!sh) return 0;
348: tmp = sh;
349: sh = sh->previous;
350: PetscFree(tmp);
351: if (!sh || !sh->handler) {
352: #if !defined(PETSC_MISSING_SIGALRM)
353: /* signal(SIGALRM, SIG_DFL); */
354: #endif
355: #if !defined(PETSC_MISSING_SIGBUS)
356: signal(SIGBUS, SIG_DFL);
357: #endif
358: #if !defined(PETSC_MISSING_SIGCONT)
359: /* signal(SIGCONT, SIG_DFL); */
360: #endif
361: #if !defined(PETSC_MISSING_SIGFPE)
362: signal(SIGFPE, SIG_DFL);
363: #endif
364: #if !defined(PETSC_MISSING_SIGHUP)
365: signal(SIGHUP, SIG_DFL);
366: #endif
367: #if !defined(PETSC_MISSING_SIGILL)
368: signal(SIGILL, SIG_DFL);
369: #endif
370: #if !defined(PETSC_MISSING_SIGINT)
371: /* signal(SIGINT, SIG_DFL); */
372: #endif
373: #if !defined(PETSC_MISSING_SIGPIPE)
374: signal(SIGPIPE, SIG_DFL);
375: #endif
376: #if !defined(PETSC_MISSING_SIGQUIT)
377: signal(SIGQUIT, SIG_DFL);
378: #endif
379: #if !defined(PETSC_MISSING_SIGSEGV)
380: signal(SIGSEGV, SIG_DFL);
381: #endif
382: #if !defined(PETSC_MISSING_SIGSYS)
383: signal(SIGSYS, SIG_DFL);
384: #endif
385: #if !defined(PETSC_MISSING_SIGTERM)
386: signal(SIGTERM, SIG_DFL);
387: #endif
388: #if !defined(PETSC_MISSING_SIGTRAP)
389: signal(SIGTRAP, SIG_DFL);
390: #endif
391: #if !defined(PETSC_MISSING_SIGTSTP)
392: /* signal(SIGTSTP, SIG_DFL); */
393: #endif
394: #if !defined(PETSC_MISSING_SIGURG)
395: signal(SIGURG, SIG_DFL);
396: #endif
397: #if !defined(PETSC_MISSING_SIGUSR1)
398: /* signal(SIGUSR1, SIG_DFL); */
399: #endif
400: #if !defined(PETSC_MISSING_SIGUSR2)
401: /* signal(SIGUSR2, SIG_DFL); */
402: #endif
403: SignalSet = PETSC_FALSE;
404: } else {
405: SignalSet = PETSC_TRUE;
406: }
407: return 0;
408: }