Actual source code: signal.c
petsc-3.7.3 2016-08-01
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> /*I "petscsys.h" I*/
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;
22: /*
23: PetscSignalHandler_Private - This is the signal handler called by the system. This calls
24: any signal handler set by PETSc or the application code.
26: Input Parameters: (depends on system)
27: . sig - integer code indicating the type of signal
28: . code - ??
29: . sigcontext - ??
30: . addr - ??
32: Note: this is declared extern "C" because it is passed to the system routine signal()
33: which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be
34: extern "C".
36: */
37: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
38: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
39: #else
40: static void PetscSignalHandler_Private(int sig)
41: #endif
42: {
46: if (!sh || !sh->handler) PetscSignalHandlerDefault(sig,(void*)0);
47: else {
48: if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
49: (*sh->handler)(sig,sh->ctx);
50: }
51: if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
52: }
56: /*@
57: PetscSignalHandlerDefault - Default signal handler.
59: Not Collective
61: Level: advanced
63: Input Parameters:
64: + sig - signal value
65: - ptr - unused pointer
67: Concepts: signal handler^default
69: @*/
70: PetscErrorCode PetscSignalHandlerDefault(int sig,void *ptr)
71: {
73: const char *SIGNAME[64];
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: (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
140: if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
141: else (*PetscErrorPrintf)("Caught signal\n");
143: (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
144: (*PetscErrorPrintf)("or see http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
145: (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n");
146: #if defined(PETSC_USE_DEBUG)
147: if (!PetscStackActive()) (*PetscErrorPrintf)(" or try option -log_stack\n");
148: else {
149: PetscStackPop; /* remove stack frames for error handlers */
150: PetscStackPop;
151: (*PetscErrorPrintf)("likely location of problem given in stack below\n");
152: (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n");
153: PetscStackView(PETSC_STDOUT);
154: }
155: #endif
156: #if !defined(PETSC_USE_DEBUG)
157: (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
158: (*PetscErrorPrintf)("to get more information on the crash.\n");
159: #endif
160: PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
161: MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
162: return(0);
163: }
165: #if !defined(PETSC_SIGNAL_CAST)
166: #define PETSC_SIGNAL_CAST
167: #endif
171: /*@C
172: PetscPushSignalHandler - Catches the usual fatal errors and
173: calls a user-provided routine.
175: Not Collective
177: Input Parameter:
178: + routine - routine to call when a signal is received
179: - ctx - optional context needed by the routine
181: Level: developer
183: Concepts: signal handler^setting
185: .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()
187: @*/
188: PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
189: {
190: 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)
213: signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
214: #endif
215: #if !defined(PETSC_MISSING_SIGILL)
216: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
217: #endif
218: #if !defined(PETSC_MISSING_SIGINT)
219: /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
220: #endif
221: #if !defined(PETSC_MISSING_SIGPIPE)
222: signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
223: #endif
224: #if !defined(PETSC_MISSING_SIGQUIT)
225: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
226: #endif
227: #if !defined(PETSC_MISSING_SIGSEGV)
228: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
229: #endif
230: #if !defined(PETSC_MISSING_SIGSYS)
231: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
232: #endif
233: #if !defined(PETSC_MISSING_SIGTERM)
234: signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
235: #endif
236: #if !defined(PETSC_MISSING_SIGTRAP)
237: signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
238: #endif
239: #if !defined(PETSC_MISSING_SIGTSTP)
240: /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
241: #endif
242: #if !defined(PETSC_MISSING_SIGURG)
243: signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
244: #endif
245: #if !defined(PETSC_MISSING_SIGUSR1)
246: /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
247: #endif
248: #if !defined(PETSC_MISSING_SIGUSR2)
249: /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
250: #endif
251: SignalSet = PETSC_TRUE;
252: }
253: if (!routine) {
254: #if !defined(PETSC_MISSING_SIGALRM)
255: /* signal(SIGALRM, 0); */
256: #endif
257: #if !defined(PETSC_MISSING_SIGBUS)
258: signal(SIGBUS, 0);
259: #endif
260: #if !defined(PETSC_MISSING_SIGCONT)
261: /* signal(SIGCONT, 0); */
262: #endif
263: #if !defined(PETSC_MISSING_SIGFPE)
264: signal(SIGFPE, 0);
265: #endif
266: #if !defined(PETSC_MISSING_SIGHUP)
267: signal(SIGHUP, 0);
268: #endif
269: #if !defined(PETSC_MISSING_SIGILL)
270: signal(SIGILL, 0);
271: #endif
272: #if !defined(PETSC_MISSING_SIGINT)
273: /* signal(SIGINT, 0); */
274: #endif
275: #if !defined(PETSC_MISSING_SIGPIPE)
276: signal(SIGPIPE, 0);
277: #endif
278: #if !defined(PETSC_MISSING_SIGQUIT)
279: signal(SIGQUIT, 0);
280: #endif
281: #if !defined(PETSC_MISSING_SIGSEGV)
282: signal(SIGSEGV, 0);
283: #endif
284: #if !defined(PETSC_MISSING_SIGSYS)
285: signal(SIGSYS, 0);
286: #endif
287: #if !defined(PETSC_MISSING_SIGTERM)
288: signal(SIGTERM, 0);
289: #endif
290: #if !defined(PETSC_MISSING_SIGTRAP)
291: signal(SIGTRAP, 0);
292: #endif
293: #if !defined(PETSC_MISSING_SIGTSTP)
294: /* signal(SIGTSTP, 0); */
295: #endif
296: #if !defined(PETSC_MISSING_SIGURG)
297: signal(SIGURG, 0);
298: #endif
299: #if !defined(PETSC_MISSING_SIGUSR1)
300: /* signal(SIGUSR1, 0); */
301: #endif
302: #if !defined(PETSC_MISSING_SIGUSR2)
303: /* signal(SIGUSR2, 0); */
304: #endif
305: SignalSet = PETSC_FALSE;
306: }
307: PetscNew(&newsh);
308: if (sh) {
309: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
310: newsh->previous = sh;
311: } else newsh->previous = 0;
312: newsh->handler = routine;
313: newsh->ctx = ctx;
314: newsh->classid = SIGNAL_CLASSID;
315: sh = newsh;
316: return(0);
317: }
321: /*@
322: PetscPopSignalHandler - Removes the most last signal handler that was pushed.
323: If no signal handlers are left on the stack it will remove the PETSc signal handler.
324: (That is PETSc will no longer catch signals).
326: Not Collective
328: Level: developer
330: Concepts: signal handler^setting
332: .seealso: PetscPushSignalHandler()
334: @*/
335: PetscErrorCode PetscPopSignalHandler(void)
336: {
337: struct SH *tmp;
340: if (!sh) return(0);
341: if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
343: tmp = sh;
344: sh = sh->previous;
345: PetscFreeVoid(tmp);
346: if (!sh || !sh->handler) {
347: #if !defined(PETSC_MISSING_SIGALRM)
348: /* signal(SIGALRM, 0); */
349: #endif
350: #if !defined(PETSC_MISSING_SIGBUS)
351: signal(SIGBUS, 0);
352: #endif
353: #if !defined(PETSC_MISSING_SIGCONT)
354: /* signal(SIGCONT, 0); */
355: #endif
356: #if !defined(PETSC_MISSING_SIGFPE)
357: signal(SIGFPE, 0);
358: #endif
359: #if !defined(PETSC_MISSING_SIGHUP)
360: signal(SIGHUP, 0);
361: #endif
362: #if !defined(PETSC_MISSING_SIGILL)
363: signal(SIGILL, 0);
364: #endif
365: #if !defined(PETSC_MISSING_SIGINT)
366: /* signal(SIGINT, 0); */
367: #endif
368: #if !defined(PETSC_MISSING_SIGPIPE)
369: signal(SIGPIPE, 0);
370: #endif
371: #if !defined(PETSC_MISSING_SIGQUIT)
372: signal(SIGQUIT, 0);
373: #endif
374: #if !defined(PETSC_MISSING_SIGSEGV)
375: signal(SIGSEGV, 0);
376: #endif
377: #if !defined(PETSC_MISSING_SIGSYS)
378: signal(SIGSYS, 0);
379: #endif
380: #if !defined(PETSC_MISSING_SIGTERM)
381: signal(SIGTERM, 0);
382: #endif
383: #if !defined(PETSC_MISSING_SIGTRAP)
384: signal(SIGTRAP, 0);
385: #endif
386: #if !defined(PETSC_MISSING_SIGTSTP)
387: /* signal(SIGTSTP, 0); */
388: #endif
389: #if !defined(PETSC_MISSING_SIGURG)
390: signal(SIGURG, 0);
391: #endif
392: #if !defined(PETSC_MISSING_SIGUSR1)
393: /* signal(SIGUSR1, 0); */
394: #endif
395: #if !defined(PETSC_MISSING_SIGUSR2)
396: /* signal(SIGUSR2, 0); */
397: #endif
398: SignalSet = PETSC_FALSE;
399: } else {
400: SignalSet = PETSC_TRUE;
401: }
402: return(0);
403: }
406: #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_SIGINFO_T)
407: #include <setjmp.h>
408: PETSC_VISIBILITY_INTERNAL jmp_buf PetscSegvJumpBuf;
409: /*
410: This routine is called if a segmentation violation, i.e. inaccessible memory access
413: It simply unrolls the UNIX signal and returns to the location where setjump(PetscSeqvJumpBuf) is declared.
414: */
415: PETSC_INTERN void PetscSegv_sigaction(int signal, siginfo_t *si, void *arg)
416: {
417: longjmp(PetscSegvJumpBuf,1);
418: return;
419: }
420: #endif