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: #undef __FUNCT__
47: /*
48: PetscSignalHandler_Private - This is the signal handler called by the system. This calls
49: any signal handler set by PETSc or the application code.
50:
51: Input Parameters: (depends on system)
52: . sig - integer code indicating the type of signal
53: . code - ??
54: . sigcontext - ??
55: . addr - ??
57: Note: this is declared extern "C" because it is passed to the system routine signal()
58: which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be
59: extern "C".
61: */
62: #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
63: static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
64: #else
65: static void PetscSignalHandler_Private(int sig)
66: #endif
67: {
71: if (!sh || !sh->handler) {
72: PetscDefaultSignalHandler(sig,(void*)0);
73: } else{
74: (*sh->handler)(sig,sh->ctx);
75: }
76: if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
77: }
78: EXTERN_C_END
80: #undef __FUNCT__
82: /*@
83: PetscDefaultSignalHandler - Default signal handler.
85: Not Collective
87: Level: advanced
89: Input Parameters:
90: + sig - signal value
91: - ptr - unused pointer
93: Concepts: signal handler^default
95: @*/
96: int PetscDefaultSignalHandler(int sig,void *ptr)
97: {
98: int ierr;
99: static char buf[1024];
102: signal(sig,SIG_DFL);
103: if (sig >= 0 && sig <= 20) {
104: sprintf(buf,"Caught signal %sn",SIGNAME[sig]);
105: } else {
106: PetscStrcpy(buf,"Caught signaln");
107: }
108: PetscStrcat(buf,"PETSC ERROR: Try option -start_in_debugger or ");
109: PetscStrcat(buf,"-on_error_attach_debugger ");
110: PetscStrcat(buf,"tonPETSC ERROR: determine where problem occursn");
111: #if defined(PETSC_USE_STACK)
112: if (!PetscStackActive) {
113: PetscStrcat(buf,"PETSC ERROR: or try option -log_stackn");
114: } else {
115: PetscStackPop; /* remove stack frames for error handlers */
116: PetscStackPop;
117: PetscStrcat(buf,"PETSC ERROR: likely location of problem given above in stackn");
118: (*PetscErrorPrintf)("--------------- Stack Frames ---------------n");
119: PetscStackView(PETSC_VIEWER_STDOUT_WORLD);
120: (*PetscErrorPrintf)("--------------------------------------------n");
121: }
122: #endif
123: #if !defined(PETSC_USE_BOPT_g)
124: PetscStrcat(buf,"PETSC ERROR: compile, link, and run with BOPT=g or g_c++ or g_complexn");
125: PetscStrcat(buf,"PETSC ERROR: to get more information on the crash.n");
126: #endif
127: PetscError(0,"User provided function","Unknown file","Unknown directory",PETSC_ERR_SIG,1,buf);
128: MPI_Abort(PETSC_COMM_WORLD,ierr);
129: return(0);
130: }
132: #if !defined(PETSC_SIGNAL_CAST)
133: #define PETSC_SIGNAL_CAST
134: #endif
136: #undef __FUNCT__
138: /*@C
139: PetscPushSignalHandler - Catches the usual fatal errors and
140: calls a user-provided routine.
142: Not Collective
144: Input Parameter:
145: + routine - routine to call when a signal is received
146: - ctx - optional context needed by the routine
148: Level: developer
150: Concepts: signal handler^setting
152: @*/
153: int PetscPushSignalHandler(int (*routine)(int,void*),void* ctx)
154: {
155: struct SH *newsh;
156: int ierr;
159: if (!SignalSet && routine) {
160: signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
161: signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
162: signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
163: #if !defined(PETSC_MISSING_SIGSYS)
164: signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
165: #endif
166: #if !defined(PETSC_MISSING_SIGBUS)
167: signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
168: #endif
169: #if !defined(PETSC_MISSING_SIGQUIT)
170: signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
171: #endif
172: SignalSet = PETSC_TRUE;
173: }
174: if (!routine) {
175: signal(SIGILL, 0);
176: signal(SIGFPE, 0);
177: signal(SIGSEGV, 0);
178: #if !defined(PETSC_MISSING_SIGSYS)
179: signal(SIGSYS, 0);
180: #endif
181: #if !defined(PETSC_MISSING_SIGBUS)
182: signal(SIGBUS, 0);
183: #endif
184: #if !defined(PETSC_MISSING_SIGQUIT)
185: signal(SIGQUIT, 0);
186: #endif
187: SignalSet = PETSC_FALSE;
188: }
189: PetscNew(struct SH,&newsh);
190: if (sh) {newsh->previous = sh;}
191: else {newsh->previous = 0;}
192: newsh->handler = routine;
193: newsh->ctx = ctx;
194: sh = newsh;
195: return(0);
196: }
198: /* NO ERROR CODES RETURNED BY THIS FUNCTION */
199: #undef __FUNCT__
201: int PetscPopSignalHandler(void)
202: {
203: struct SH *tmp;
206: if (!sh) return(0);
207: tmp = sh;
208: sh = sh->previous;
209: PetscFree(tmp);
210: if (!sh || !sh->handler) {
211: signal(SIGILL, 0);
212: signal(SIGFPE, 0);
213: signal(SIGSEGV, 0);
214: #if !defined(PETSC_MISSING_SIGSYS)
215: signal(SIGSYS, 0);
216: #endif
217: #if !defined(PETSC_MISSING_SIGBUS)
218: signal(SIGBUS, 0);
219: #endif
220: #if !defined(PETSC_MISSING_SIGQUIT)
221: signal(SIGQUIT, 0);
222: #endif
223: SignalSet = PETSC_FALSE;
224: } else {
225: SignalSet = PETSC_TRUE;
226: }
227: return(0);
228: }