Actual source code: signal.c
petsc-3.12.5 2020-03-29
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>
9: static PetscClassId SIGNAL_CLASSID = 0;
11: struct SH {
12: PetscClassId classid;
13: PetscErrorCode (*handler)(int,void*);
14: void *ctx;
15: struct SH *previous;
16: };
17: static struct SH *sh = 0;
18: static PetscBool SignalSet = PETSC_FALSE;
20: /*
21: PetscSignalHandler_Private - This is the signal handler called by the system. This calls
22: any signal handler set by PETSc or the application code.
24: Input Parameters: (depends on system)
25: . sig - integer code indicating the type of signal
26: . code - ??
27: . sigcontext - ??
28: . addr - ??
30: */
31: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
32: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
33: #else
34: static void PetscSignalHandler_Private(int sig)
35: #endif
36: {
40: if (!sh || !sh->handler) PetscSignalHandlerDefault(sig,(void*)0);
41: else {
42: if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
43: (*sh->handler)(sig,sh->ctx);
44: }
45: if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
46: }
48: /*@
49: PetscSignalHandlerDefault - Default signal handler.
51: Not Collective
53: Level: advanced
55: Input Parameters:
56: + sig - signal value
57: - ptr - unused pointer
59: @*/
60: PetscErrorCode PetscSignalHandlerDefault(int sig,void *ptr)
61: {
63: const char *SIGNAME[64];
66: if (sig == SIGSEGV) PetscSignalSegvCheckPointer();
67: SIGNAME[0] = "Unknown signal";
68: #if !defined(PETSC_MISSING_SIGABRT)
69: SIGNAME[SIGABRT] = "Abort";
70: #endif
71: #if !defined(PETSC_MISSING_SIGALRM)
72: SIGNAME[SIGALRM] = "Alarm";
73: #endif
74: #if !defined(PETSC_MISSING_SIGBUS)
75: SIGNAME[SIGBUS] = "BUS: Bus Error, possibly illegal memory access";
76: #endif
77: #if !defined(PETSC_MISSING_SIGCHLD)
78: SIGNAME[SIGCHLD] = "CHLD";
79: #endif
80: #if !defined(PETSC_MISSING_SIGCONT)
81: SIGNAME[SIGCONT] = "CONT";
82: #endif
83: #if !defined(PETSC_MISSING_SIGFPE)
84: SIGNAME[SIGFPE] = "FPE: Floating Point Exception,probably divide by zero";
85: #endif
86: #if !defined(PETSC_MISSING_SIGHUP)
87: SIGNAME[SIGHUP] = "Hang up: Some other process (or the batch system) has told this process to end";
88: #endif
89: #if !defined(PETSC_MISSING_SIGILL)
90: SIGNAME[SIGILL] = "Illegal instruction: Likely due to memory corruption";
91: #endif
92: #if !defined(PETSC_MISSING_SIGINT)
93: SIGNAME[SIGINT] = "Interrupt";
94: #endif
95: #if !defined(PETSC_MISSING_SIGKILL)
96: SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
97: #endif
98: #if !defined(PETSC_MISSING_SIGPIPE)
99: SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
100: #endif
101: #if !defined(PETSC_MISSING_SIGQUIT)
102: SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
103: #endif
104: #if !defined(PETSC_MISSING_SIGSEGV)
105: SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
106: #endif
107: #if !defined(PETSC_MISSING_SIGSYS)
108: SIGNAME[SIGSYS] = "SYS";
109: #endif
110: #if !defined(PETSC_MISSING_SIGTERM)
111: SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end";
112: #endif
113: #if !defined(PETSC_MISSING_SIGTRAP)
114: SIGNAME[SIGTRAP] = "TRAP";
115: #endif
116: #if !defined(PETSC_MISSING_SIGTSTP)
117: SIGNAME[SIGTSTP] = "TSTP";
118: #endif
119: #if !defined(PETSC_MISSING_SIGURG)
120: SIGNAME[SIGURG] = "URG";
121: #endif
122: #if !defined(PETSC_MISSING_SIGUSR1)
123: SIGNAME[SIGUSR1] = "User 1";
124: #endif
125: #if !defined(PETSC_MISSING_SIGUSR2)
126: SIGNAME[SIGUSR2] = "User 2";
127: #endif
129: signal(sig,SIG_DFL);
130: (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
131: if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
132: else (*PetscErrorPrintf)("Caught signal\n");
134: (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
135: (*PetscErrorPrintf)("or see https://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
136: (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
137: #if defined(PETSC_USE_DEBUG)
138: if (!PetscStackActive()) (*PetscErrorPrintf)(" or try option -log_stack\n");
139: else {
140: PetscStackPop; /* remove stack frames for error handlers */
141: PetscStackPop;
142: (*PetscErrorPrintf)("likely location of problem given in stack below\n");
143: (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
144: PetscStackView(PETSC_STDOUT);
145: }
146: #endif
147: #if !defined(PETSC_USE_DEBUG)
148: (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
149: (*PetscErrorPrintf)("to get more information on the crash.\n");
150: #endif
151: PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
152: MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
153: return(0);
154: }
156: #if !defined(PETSC_SIGNAL_CAST)
157: #define PETSC_SIGNAL_CAST
158: #endif
160: /*@C
161: PetscPushSignalHandler - Catches the usual fatal errors and
162: calls a user-provided routine.
164: Not Collective
166: Input Parameter:
167: + routine - routine to call when a signal is received
168: - ctx - optional context needed by the routine
170: Level: developer
172: .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()
174: @*/
175: PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
176: {
177: struct SH *newsh;
181: if (!SIGNAL_CLASSID) {
182: /* PetscClassIdRegister("Signal",&SIGNAL_CLASSID); */
183: SIGNAL_CLASSID = 19;
184: }
185: if (!SignalSet && routine) {
186: /* Do not catch ABRT, CHLD, KILL */
187: #if !defined(PETSC_MISSING_SIGALRM)
188: /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
189: #endif
190: #if !defined(PETSC_MISSING_SIGBUS)
191: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
192: #endif
193: #if !defined(PETSC_MISSING_SIGCONT)
194: /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
195: #endif
196: #if !defined(PETSC_MISSING_SIGFPE)
197: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
198: #endif
199: #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION)
200: {
201: struct sigaction action;
202: sigaction(SIGHUP,NULL,&action);
203: if (action.sa_handler == SIG_IGN) {
204: PetscInfo(NULL,"SIGHUP previously set to ignore, therefor not changing its signal handler\n");
205: } else {
206: signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
207: }
208: }
209: #endif
210: #if !defined(PETSC_MISSING_SIGILL)
211: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
212: #endif
213: #if !defined(PETSC_MISSING_SIGINT)
214: /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
215: #endif
216: #if !defined(PETSC_MISSING_SIGPIPE)
217: signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
218: #endif
219: #if !defined(PETSC_MISSING_SIGQUIT)
220: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
221: #endif
222: #if !defined(PETSC_MISSING_SIGSEGV)
223: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
224: #endif
225: #if !defined(PETSC_MISSING_SIGSYS)
226: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
227: #endif
228: #if !defined(PETSC_MISSING_SIGTERM)
229: signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
230: #endif
231: #if !defined(PETSC_MISSING_SIGTRAP)
232: signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
233: #endif
234: #if !defined(PETSC_MISSING_SIGTSTP)
235: /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
236: #endif
237: #if !defined(PETSC_MISSING_SIGURG)
238: signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
239: #endif
240: #if !defined(PETSC_MISSING_SIGUSR1)
241: /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
242: #endif
243: #if !defined(PETSC_MISSING_SIGUSR2)
244: /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
245: #endif
246: SignalSet = PETSC_TRUE;
247: }
248: if (!routine) {
249: #if !defined(PETSC_MISSING_SIGALRM)
250: /* signal(SIGALRM, 0); */
251: #endif
252: #if !defined(PETSC_MISSING_SIGBUS)
253: signal(SIGBUS, 0);
254: #endif
255: #if !defined(PETSC_MISSING_SIGCONT)
256: /* signal(SIGCONT, 0); */
257: #endif
258: #if !defined(PETSC_MISSING_SIGFPE)
259: signal(SIGFPE, 0);
260: #endif
261: #if !defined(PETSC_MISSING_SIGHUP)
262: signal(SIGHUP, 0);
263: #endif
264: #if !defined(PETSC_MISSING_SIGILL)
265: signal(SIGILL, 0);
266: #endif
267: #if !defined(PETSC_MISSING_SIGINT)
268: /* signal(SIGINT, 0); */
269: #endif
270: #if !defined(PETSC_MISSING_SIGPIPE)
271: signal(SIGPIPE, 0);
272: #endif
273: #if !defined(PETSC_MISSING_SIGQUIT)
274: signal(SIGQUIT, 0);
275: #endif
276: #if !defined(PETSC_MISSING_SIGSEGV)
277: signal(SIGSEGV, 0);
278: #endif
279: #if !defined(PETSC_MISSING_SIGSYS)
280: signal(SIGSYS, 0);
281: #endif
282: #if !defined(PETSC_MISSING_SIGTERM)
283: signal(SIGTERM, 0);
284: #endif
285: #if !defined(PETSC_MISSING_SIGTRAP)
286: signal(SIGTRAP, 0);
287: #endif
288: #if !defined(PETSC_MISSING_SIGTSTP)
289: /* signal(SIGTSTP, 0); */
290: #endif
291: #if !defined(PETSC_MISSING_SIGURG)
292: signal(SIGURG, 0);
293: #endif
294: #if !defined(PETSC_MISSING_SIGUSR1)
295: /* signal(SIGUSR1, 0); */
296: #endif
297: #if !defined(PETSC_MISSING_SIGUSR2)
298: /* signal(SIGUSR2, 0); */
299: #endif
300: SignalSet = PETSC_FALSE;
301: }
302: PetscNew(&newsh);
303: if (sh) {
304: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
305: newsh->previous = sh;
306: } else newsh->previous = 0;
307: newsh->handler = routine;
308: newsh->ctx = ctx;
309: newsh->classid = SIGNAL_CLASSID;
310: sh = newsh;
311: return(0);
312: }
314: /*@
315: PetscPopSignalHandler - Removes the most last signal handler that was pushed.
316: If no signal handlers are left on the stack it will remove the PETSc signal handler.
317: (That is PETSc will no longer catch signals).
319: Not Collective
321: Level: developer
323: .seealso: PetscPushSignalHandler()
325: @*/
326: PetscErrorCode PetscPopSignalHandler(void)
327: {
328: struct SH *tmp;
332: if (!sh) return(0);
333: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
335: tmp = sh;
336: sh = sh->previous;
337: PetscFree(tmp);
338: if (!sh || !sh->handler) {
339: #if !defined(PETSC_MISSING_SIGALRM)
340: /* signal(SIGALRM, 0); */
341: #endif
342: #if !defined(PETSC_MISSING_SIGBUS)
343: signal(SIGBUS, 0);
344: #endif
345: #if !defined(PETSC_MISSING_SIGCONT)
346: /* signal(SIGCONT, 0); */
347: #endif
348: #if !defined(PETSC_MISSING_SIGFPE)
349: signal(SIGFPE, 0);
350: #endif
351: #if !defined(PETSC_MISSING_SIGHUP)
352: signal(SIGHUP, 0);
353: #endif
354: #if !defined(PETSC_MISSING_SIGILL)
355: signal(SIGILL, 0);
356: #endif
357: #if !defined(PETSC_MISSING_SIGINT)
358: /* signal(SIGINT, 0); */
359: #endif
360: #if !defined(PETSC_MISSING_SIGPIPE)
361: signal(SIGPIPE, 0);
362: #endif
363: #if !defined(PETSC_MISSING_SIGQUIT)
364: signal(SIGQUIT, 0);
365: #endif
366: #if !defined(PETSC_MISSING_SIGSEGV)
367: signal(SIGSEGV, 0);
368: #endif
369: #if !defined(PETSC_MISSING_SIGSYS)
370: signal(SIGSYS, 0);
371: #endif
372: #if !defined(PETSC_MISSING_SIGTERM)
373: signal(SIGTERM, 0);
374: #endif
375: #if !defined(PETSC_MISSING_SIGTRAP)
376: signal(SIGTRAP, 0);
377: #endif
378: #if !defined(PETSC_MISSING_SIGTSTP)
379: /* signal(SIGTSTP, 0); */
380: #endif
381: #if !defined(PETSC_MISSING_SIGURG)
382: signal(SIGURG, 0);
383: #endif
384: #if !defined(PETSC_MISSING_SIGUSR1)
385: /* signal(SIGUSR1, 0); */
386: #endif
387: #if !defined(PETSC_MISSING_SIGUSR2)
388: /* signal(SIGUSR2, 0); */
389: #endif
390: SignalSet = PETSC_FALSE;
391: } else {
392: SignalSet = PETSC_TRUE;
393: }
394: return(0);
395: }