Actual source code: signal.c
1: /*$Id: signal.c,v 1.76 2001/03/23 23:20:26 balay Exp $*/
2: /*
3: Routines to handle signals the program will receive.
4: Usually this will call the error handlers.
5: */
6: #include <signal.h>
7: #include petsc.h
8: #include petscsys.h
9: #include "petscfix.h"
11: struct SH {
12: int cookie;
13: int (*handler)(int,void *);
14: void *ctx;
15: struct SH* previous;
16: };
17: static struct SH* sh = 0;
18: static PetscTruth SignalSet = PETSC_FALSE;
20: static char *SIGNAME[] = {
21: "Unknown signal",
22: "HUP",
23: "INT",
24: "QUIT",
25: "ILL",
26: "TRAP",
27: "ABRT",
28: "EMT",
29: "FPE:nPETSC ERROR: Floating Point Exception,probably divide by zero",
30: "KILL",
31: "BUS: nPETSC ERROR: Bus Error, possibly illegal memory access",
32: "SEGV:nPETSC ERROR: Segmentation Violation, probably memory access out of range",
33: "SYS",
34: "PIPE",
35: "ALRM",
36: "TERM",
37: "URG",
38: "STOP",
39: "TSTP",
40: "CONT",
41: "CHLD" };
44: EXTERN_C_BEGIN
45: /*
46: PetscSignalHandler_Private - This is the signal handler called by the system. This calls
47: any signal handler set by PETSc or the application code.
48:
49: Input Parameters: (depends on system)
50: . sig - integer code indicating the type of signal
51: . code - ??
52: . sigcontext - ??
53: . addr - ??
55: Note: this is declared extern "C" because it is passed to the system routine signal()
56: which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be
57: extern "C".
59: */
60: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
61: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
62: #else
63: static void PetscSignalHandler_Private(int sig)
64: #endif
65: {
69: if (!sh || !sh->handler) {
70: PetscDefaultSignalHandler(sig,(void*)0);
71: } else{
72: (*sh->handler)(sig,sh->ctx);
73: }
74: if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
75: }
76: EXTERN_C_END
78: /*@
79: PetscDefaultSignalHandler - Default signal handler.
81: Not Collective
83: Level: advanced
85: Input Parameters:
86: + sig - signal value
87: - ptr - unused pointer
89: Concepts: signal handler^default
91: @*/
92: int PetscDefaultSignalHandler(int sig,void *ptr)
93: {
94: int ierr;
95: static char buf[1024];
98: signal(sig,SIG_DFL);
99: if (sig >= 0 && sig <= 20) {
100: sprintf(buf,"Caught signal %sn",SIGNAME[sig]);
101: } else {
102: PetscStrcpy(buf,"Caught signaln");
103: }
104: PetscStrcat(buf,"PETSC ERROR: Try option -start_in_debugger or ");
105: PetscStrcat(buf,"-on_error_attach_debugger ");
106: PetscStrcat(buf,"tonPETSC ERROR: determine where problem occursn");
107: #if defined(PETSC_USE_STACK)
108: if (!PetscStackActive) {
109: PetscStrcat(buf,"PETSC ERROR: or try option -log_stackn");
110: } else {
111: PetscStackPop; /* remove stack frames for error handlers */
112: PetscStackPop;
113: PetscStrcat(buf,"PETSC ERROR: likely location of problem given above in stackn");
114: (*PetscErrorPrintf)("--------------- Stack Frames ---------------n");
115: PetscStackView(PETSC_VIEWER_STDOUT_WORLD);
116: (*PetscErrorPrintf)("--------------------------------------------n");
117: }
118: #endif
119: PetscError(0,"unknownfunction","unknown file"," ",PETSC_ERR_SIG,0,buf);
120: MPI_Abort(PETSC_COMM_WORLD,ierr);
121: return(0);
122: }
124: #if !defined(PETSC_SIGNAL_CAST)
125: #define PETSC_SIGNAL_CAST
126: #endif
128: /*@C
129: PetscPushSignalHandler - Catches the usual fatal errors and
130: calls a user-provided routine.
132: Not Collective
134: Input Parameter:
135: + routine - routine to call when a signal is received
136: - ctx - optional context needed by the routine
138: Level: developer
140: Concepts: signal handler^setting
142: @*/
143: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
144: {
145: struct SH *newsh;
146: int ierr;
149: if (!SignalSet && routine) {
150: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
151: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
152: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
153: #if !defined(PETSC_MISSING_SIGSYS)
154: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
155: #endif
156: #if !defined(PETSC_MISSING_SIGBUS)
157: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
158: #endif
159: #if !defined(PETSC_MISSING_SIGQUIT)
160: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
161: #endif
162: SignalSet = PETSC_TRUE;
163: }
164: if (!routine) {
165: signal(SIGILL, 0);
166: signal(SIGFPE, 0);
167: signal(SIGSEGV, 0);
168: #if !defined(PETSC_MISSING_SIGSYS)
169: signal(SIGSYS, 0);
170: #endif
171: #if !defined(PETSC_MISSING_SIGBUS)
172: signal(SIGBUS, 0);
173: #endif
174: #if !defined(PETSC_MISSING_SIGQUIT)
175: signal(SIGQUIT, 0);
176: #endif
177: SignalSet = PETSC_FALSE;
178: }
179: PetscNew(struct SH,&newsh);
180: if (sh) {newsh->previous = sh;}
181: else {newsh->previous = 0;}
182: newsh->handler = routine;
183: newsh->ctx = ctx;
184: sh = newsh;
185: return(0);
186: }
188: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
189: int PetscPopSignalHandler(void)
190: {
191: struct SH *tmp;
194: if (!sh) return(0);
195: tmp = sh;
196: sh = sh->previous;
197: PetscFree(tmp);
198: if (!sh || !sh->handler) {
199: signal(SIGILL, 0);
200: signal(SIGFPE, 0);
201: signal(SIGSEGV, 0);
202: #if !defined(PETSC_MISSING_SIGSYS)
203: signal(SIGSYS, 0);
204: #endif
205: #if !defined(PETSC_MISSING_SIGBUS)
206: signal(SIGBUS, 0);
207: #endif
208: #if !defined(PETSC_MISSING_SIGQUIT)
209: signal(SIGQUIT, 0);
210: #endif
211: SignalSet = PETSC_FALSE;
212: } else {
213: SignalSet = PETSC_TRUE;
214: }
215: return(0);
216: }