Actual source code: signal.c
1: /*$Id: signal.c,v 1.80 2001/04/23 15:47:54 bsmith 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: #if !defined(PETSC_USE_BOPT_g)
120: PetscStrcat(buf,"PETSC ERROR: compile, link, and run with BOPT=g or g_c++ or g_complexn");
121: PetscStrcat(buf,"PETSC ERROR: to get more information on the crash.n");
122: #endif
123: PetscError(0,"unknownfunction","Unknown file","Unknown directory",PETSC_ERR_SIG,1,buf);
124: MPI_Abort(PETSC_COMM_WORLD,ierr);
125: return(0);
126: }
128: #if !defined(PETSC_SIGNAL_CAST)
129: #define PETSC_SIGNAL_CAST
130: #endif
132: /*@C
133: PetscPushSignalHandler - Catches the usual fatal errors and
134: calls a user-provided routine.
136: Not Collective
138: Input Parameter:
139: + routine - routine to call when a signal is received
140: - ctx - optional context needed by the routine
142: Level: developer
144: Concepts: signal handler^setting
146: @*/
147: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
148: {
149: struct SH *newsh;
150: int ierr;
153: if (!SignalSet && routine) {
154: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
155: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
156: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
157: #if !defined(PETSC_MISSING_SIGSYS)
158: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
159: #endif
160: #if !defined(PETSC_MISSING_SIGBUS)
161: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
162: #endif
163: #if !defined(PETSC_MISSING_SIGQUIT)
164: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
165: #endif
166: SignalSet = PETSC_TRUE;
167: }
168: if (!routine) {
169: signal(SIGILL, 0);
170: signal(SIGFPE, 0);
171: signal(SIGSEGV, 0);
172: #if !defined(PETSC_MISSING_SIGSYS)
173: signal(SIGSYS, 0);
174: #endif
175: #if !defined(PETSC_MISSING_SIGBUS)
176: signal(SIGBUS, 0);
177: #endif
178: #if !defined(PETSC_MISSING_SIGQUIT)
179: signal(SIGQUIT, 0);
180: #endif
181: SignalSet = PETSC_FALSE;
182: }
183: PetscNew(struct SH,&newsh);
184: if (sh) {newsh->previous = sh;}
185: else {newsh->previous = 0;}
186: newsh->handler = routine;
187: newsh->ctx = ctx;
188: sh = newsh;
189: return(0);
190: }
192: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
193: int PetscPopSignalHandler(void)
194: {
195: struct SH *tmp;
198: if (!sh) return(0);
199: tmp = sh;
200: sh = sh->previous;
201: PetscFree(tmp);
202: if (!sh || !sh->handler) {
203: signal(SIGILL, 0);
204: signal(SIGFPE, 0);
205: signal(SIGSEGV, 0);
206: #if !defined(PETSC_MISSING_SIGSYS)
207: signal(SIGSYS, 0);
208: #endif
209: #if !defined(PETSC_MISSING_SIGBUS)
210: signal(SIGBUS, 0);
211: #endif
212: #if !defined(PETSC_MISSING_SIGQUIT)
213: signal(SIGQUIT, 0);
214: #endif
215: SignalSet = PETSC_FALSE;
216: } else {
217: SignalSet = PETSC_TRUE;
218: }
219: return(0);
220: }