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