Actual source code: signal.c
petsc-3.10.2 2018-10-09
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: Concepts: signal handler^default
61: @*/
62: PetscErrorCode PetscSignalHandlerDefault(int sig,void *ptr)
63: {
65: const char *SIGNAME[64];
68: SIGNAME[0] = "Unknown signal";
69: #if !defined(PETSC_MISSING_SIGABRT)
70: SIGNAME[SIGABRT] = "Abort";
71: #endif
72: #if !defined(PETSC_MISSING_SIGALRM)
73: SIGNAME[SIGALRM] = "Alarm";
74: #endif
75: #if !defined(PETSC_MISSING_SIGBUS)
76: SIGNAME[SIGBUS] = "BUS: Bus Error, possibly illegal memory access";
77: #endif
78: #if !defined(PETSC_MISSING_SIGCHLD)
79: SIGNAME[SIGCHLD] = "CHLD";
80: #endif
81: #if !defined(PETSC_MISSING_SIGCONT)
82: SIGNAME[SIGCONT] = "CONT";
83: #endif
84: #if !defined(PETSC_MISSING_SIGFPE)
85: SIGNAME[SIGFPE] = "FPE: Floating Point Exception,probably divide by zero";
86: #endif
87: #if !defined(PETSC_MISSING_SIGHUP)
88: SIGNAME[SIGHUP] = "Hang up: Some other process (or the batch system) has told this process to end";
89: #endif
90: #if !defined(PETSC_MISSING_SIGILL)
91: SIGNAME[SIGILL] = "Illegal instruction: Likely due to memory corruption";
92: #endif
93: #if !defined(PETSC_MISSING_SIGINT)
94: SIGNAME[SIGINT] = "Interrupt";
95: #endif
96: #if !defined(PETSC_MISSING_SIGKILL)
97: SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
98: #endif
99: #if !defined(PETSC_MISSING_SIGPIPE)
100: SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
101: #endif
102: #if !defined(PETSC_MISSING_SIGQUIT)
103: SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
104: #endif
105: #if !defined(PETSC_MISSING_SIGSEGV)
106: SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
107: #endif
108: #if !defined(PETSC_MISSING_SIGSYS)
109: SIGNAME[SIGSYS] = "SYS";
110: #endif
111: #if !defined(PETSC_MISSING_SIGTERM)
112: SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end";
113: #endif
114: #if !defined(PETSC_MISSING_SIGTRAP)
115: SIGNAME[SIGTRAP] = "TRAP";
116: #endif
117: #if !defined(PETSC_MISSING_SIGTSTP)
118: SIGNAME[SIGTSTP] = "TSTP";
119: #endif
120: #if !defined(PETSC_MISSING_SIGURG)
121: SIGNAME[SIGURG] = "URG";
122: #endif
123: #if !defined(PETSC_MISSING_SIGUSR1)
124: SIGNAME[SIGUSR1] = "User 1";
125: #endif
126: #if !defined(PETSC_MISSING_SIGUSR2)
127: SIGNAME[SIGUSR2] = "User 2";
128: #endif
130: signal(sig,SIG_DFL);
131: (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
132: if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
133: else (*PetscErrorPrintf)("Caught signal\n");
135: (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
136: (*PetscErrorPrintf)("or see http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
137: (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
138: #if defined(PETSC_USE_DEBUG)
139: if (!PetscStackActive()) (*PetscErrorPrintf)(" or try option -log_stack\n");
140: else {
141: PetscStackPop; /* remove stack frames for error handlers */
142: PetscStackPop;
143: (*PetscErrorPrintf)("likely location of problem given in stack below\n");
144: (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
145: PetscStackView(PETSC_STDOUT);
146: }
147: #endif
148: #if !defined(PETSC_USE_DEBUG)
149: (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
150: (*PetscErrorPrintf)("to get more information on the crash.\n");
151: #endif
152: PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
153: MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
154: return(0);
155: }
157: #if !defined(PETSC_SIGNAL_CAST)
158: #define PETSC_SIGNAL_CAST
159: #endif
161: /*@C
162: PetscPushSignalHandler - Catches the usual fatal errors and
163: calls a user-provided routine.
165: Not Collective
167: Input Parameter:
168: + routine - routine to call when a signal is received
169: - ctx - optional context needed by the routine
171: Level: developer
173: Concepts: signal handler^setting
175: .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()
177: @*/
178: PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
179: {
180: struct SH *newsh;
184: if (!SIGNAL_CLASSID) {
185: /* PetscClassIdRegister("Signal",&SIGNAL_CLASSID); */
186: SIGNAL_CLASSID = 19;
187: }
188: if (!SignalSet && routine) {
189: /* Do not catch ABRT, CHLD, KILL */
190: #if !defined(PETSC_MISSING_SIGALRM)
191: /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
192: #endif
193: #if !defined(PETSC_MISSING_SIGBUS)
194: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
195: #endif
196: #if !defined(PETSC_MISSING_SIGCONT)
197: /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
198: #endif
199: #if !defined(PETSC_MISSING_SIGFPE)
200: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
201: #endif
202: #if !defined(PETSC_MISSING_SIGHUP)
203: signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
204: #endif
205: #if !defined(PETSC_MISSING_SIGILL)
206: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
207: #endif
208: #if !defined(PETSC_MISSING_SIGINT)
209: /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
210: #endif
211: #if !defined(PETSC_MISSING_SIGPIPE)
212: signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
213: #endif
214: #if !defined(PETSC_MISSING_SIGQUIT)
215: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
216: #endif
217: #if !defined(PETSC_MISSING_SIGSEGV)
218: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
219: #endif
220: #if !defined(PETSC_MISSING_SIGSYS)
221: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
222: #endif
223: #if !defined(PETSC_MISSING_SIGTERM)
224: signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
225: #endif
226: #if !defined(PETSC_MISSING_SIGTRAP)
227: signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
228: #endif
229: #if !defined(PETSC_MISSING_SIGTSTP)
230: /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
231: #endif
232: #if !defined(PETSC_MISSING_SIGURG)
233: signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
234: #endif
235: #if !defined(PETSC_MISSING_SIGUSR1)
236: /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
237: #endif
238: #if !defined(PETSC_MISSING_SIGUSR2)
239: /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
240: #endif
241: SignalSet = PETSC_TRUE;
242: }
243: if (!routine) {
244: #if !defined(PETSC_MISSING_SIGALRM)
245: /* signal(SIGALRM, 0); */
246: #endif
247: #if !defined(PETSC_MISSING_SIGBUS)
248: signal(SIGBUS, 0);
249: #endif
250: #if !defined(PETSC_MISSING_SIGCONT)
251: /* signal(SIGCONT, 0); */
252: #endif
253: #if !defined(PETSC_MISSING_SIGFPE)
254: signal(SIGFPE, 0);
255: #endif
256: #if !defined(PETSC_MISSING_SIGHUP)
257: signal(SIGHUP, 0);
258: #endif
259: #if !defined(PETSC_MISSING_SIGILL)
260: signal(SIGILL, 0);
261: #endif
262: #if !defined(PETSC_MISSING_SIGINT)
263: /* signal(SIGINT, 0); */
264: #endif
265: #if !defined(PETSC_MISSING_SIGPIPE)
266: signal(SIGPIPE, 0);
267: #endif
268: #if !defined(PETSC_MISSING_SIGQUIT)
269: signal(SIGQUIT, 0);
270: #endif
271: #if !defined(PETSC_MISSING_SIGSEGV)
272: signal(SIGSEGV, 0);
273: #endif
274: #if !defined(PETSC_MISSING_SIGSYS)
275: signal(SIGSYS, 0);
276: #endif
277: #if !defined(PETSC_MISSING_SIGTERM)
278: signal(SIGTERM, 0);
279: #endif
280: #if !defined(PETSC_MISSING_SIGTRAP)
281: signal(SIGTRAP, 0);
282: #endif
283: #if !defined(PETSC_MISSING_SIGTSTP)
284: /* signal(SIGTSTP, 0); */
285: #endif
286: #if !defined(PETSC_MISSING_SIGURG)
287: signal(SIGURG, 0);
288: #endif
289: #if !defined(PETSC_MISSING_SIGUSR1)
290: /* signal(SIGUSR1, 0); */
291: #endif
292: #if !defined(PETSC_MISSING_SIGUSR2)
293: /* signal(SIGUSR2, 0); */
294: #endif
295: SignalSet = PETSC_FALSE;
296: }
297: PetscNew(&newsh);
298: if (sh) {
299: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
300: newsh->previous = sh;
301: } else newsh->previous = 0;
302: newsh->handler = routine;
303: newsh->ctx = ctx;
304: newsh->classid = SIGNAL_CLASSID;
305: sh = newsh;
306: return(0);
307: }
309: /*@
310: PetscPopSignalHandler - Removes the most last signal handler that was pushed.
311: If no signal handlers are left on the stack it will remove the PETSc signal handler.
312: (That is PETSc will no longer catch signals).
314: Not Collective
316: Level: developer
318: Concepts: signal handler^setting
320: .seealso: PetscPushSignalHandler()
322: @*/
323: PetscErrorCode PetscPopSignalHandler(void)
324: {
325: struct SH *tmp;
329: if (!sh) return(0);
330: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
332: tmp = sh;
333: sh = sh->previous;
334: PetscFree(tmp);
335: if (!sh || !sh->handler) {
336: #if !defined(PETSC_MISSING_SIGALRM)
337: /* signal(SIGALRM, 0); */
338: #endif
339: #if !defined(PETSC_MISSING_SIGBUS)
340: signal(SIGBUS, 0);
341: #endif
342: #if !defined(PETSC_MISSING_SIGCONT)
343: /* signal(SIGCONT, 0); */
344: #endif
345: #if !defined(PETSC_MISSING_SIGFPE)
346: signal(SIGFPE, 0);
347: #endif
348: #if !defined(PETSC_MISSING_SIGHUP)
349: signal(SIGHUP, 0);
350: #endif
351: #if !defined(PETSC_MISSING_SIGILL)
352: signal(SIGILL, 0);
353: #endif
354: #if !defined(PETSC_MISSING_SIGINT)
355: /* signal(SIGINT, 0); */
356: #endif
357: #if !defined(PETSC_MISSING_SIGPIPE)
358: signal(SIGPIPE, 0);
359: #endif
360: #if !defined(PETSC_MISSING_SIGQUIT)
361: signal(SIGQUIT, 0);
362: #endif
363: #if !defined(PETSC_MISSING_SIGSEGV)
364: signal(SIGSEGV, 0);
365: #endif
366: #if !defined(PETSC_MISSING_SIGSYS)
367: signal(SIGSYS, 0);
368: #endif
369: #if !defined(PETSC_MISSING_SIGTERM)
370: signal(SIGTERM, 0);
371: #endif
372: #if !defined(PETSC_MISSING_SIGTRAP)
373: signal(SIGTRAP, 0);
374: #endif
375: #if !defined(PETSC_MISSING_SIGTSTP)
376: /* signal(SIGTSTP, 0); */
377: #endif
378: #if !defined(PETSC_MISSING_SIGURG)
379: signal(SIGURG, 0);
380: #endif
381: #if !defined(PETSC_MISSING_SIGUSR1)
382: /* signal(SIGUSR1, 0); */
383: #endif
384: #if !defined(PETSC_MISSING_SIGUSR2)
385: /* signal(SIGUSR2, 0); */
386: #endif
387: SignalSet = PETSC_FALSE;
388: } else {
389: SignalSet = PETSC_TRUE;
390: }
391: return(0);
392: }
395: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_SIGINFO_T)
396: #include <setjmp.h>
397: PETSC_VISIBILITY_INTERNAL jmp_buf PetscSegvJumpBuf;
398: /*
399: This routine is called if a segmentation violation, i.e. inaccessible memory access
402: It simply unrolls the UNIX signal and returns to the location where setjump(PetscSeqvJumpBuf) is declared.
403: */
404: PETSC_INTERN void PetscSegv_sigaction(int signal, siginfo_t *si, void *arg)
405: {
406: longjmp(PetscSegvJumpBuf,1);
407: return;
408: }
409: #endif