xref: /petsc/src/sys/error/signal.c (revision 156ba1f8200b7ba3cb26e575f83fbb4cec653f15)
1 #define PETSC_DLL
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"             /*I   "petsc.h"   I*/
8 #include "petscsys.h"
9 #include "petscfix.h"
10 
11 static PetscCookie SIGNAL_COOKIE = 0;
12 
13 struct SH {
14   PetscCookie    cookie;
15   PetscErrorCode (*handler)(int,void *);
16   void           *ctx;
17   struct SH*     previous;
18 };
19 static struct SH* sh        = 0;
20 static PetscTruth SignalSet = PETSC_FALSE;
21 
22 
23 
24 EXTERN_C_BEGIN
25 #undef __FUNCT__
26 #define __FUNCT__ "PetscSignalHandler_Private"
27 /*
28     PetscSignalHandler_Private - This is the signal handler called by the system. This calls
29              any signal handler set by PETSc or the application code.
30 
31    Input Parameters: (depends on system)
32 .    sig - integer code indicating the type of signal
33 .    code - ??
34 .    sigcontext - ??
35 .    addr - ??
36 
37     Note: this is declared extern "C" because it is passed to the system routine signal()
38           which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be
39           extern "C".
40 
41 */
42 #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
43 static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
44 #else
45 static void PetscSignalHandler_Private(int sig)
46 #endif
47 {
48   PetscErrorCode ierr;
49 
50   PetscFunctionBegin;
51   if (!sh || !sh->handler) {
52     ierr = PetscDefaultSignalHandler(sig,(void*)0);
53   } else{
54     if (sh->cookie != SIGNAL_COOKIE) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
55     ierr = (*sh->handler)(sig,sh->ctx);
56   }
57   if (ierr) MPI_Abort(PETSC_COMM_WORLD,0);
58 }
59 EXTERN_C_END
60 
61 #undef __FUNCT__
62 #define __FUNCT__ "PetscDefaultSignalHandler"
63 /*@
64    PetscDefaultSignalHandler - Default signal handler.
65 
66    Not Collective
67 
68    Level: advanced
69 
70    Input Parameters:
71 +  sig - signal value
72 -  ptr - unused pointer
73 
74    Concepts: signal handler^default
75 
76 @*/
77 PetscErrorCode PETSC_DLLEXPORT PetscDefaultSignalHandler(int sig,void *ptr)
78 {
79   PetscErrorCode ierr;
80   const char     *SIGNAME[64];
81 
82   PetscFunctionBegin;
83   SIGNAME[0]       = "Unknown signal";
84 #if !defined(PETSC_MISSING_SIGABRT)
85   SIGNAME[SIGABRT] = "Abort";
86 #endif
87 #if !defined(PETSC_MISSING_SIGALRM)
88   /* SIGNAME[SIGALRM] = "Alarm"; */
89 #endif
90 #if !defined(PETSC_MISSING_SIGBUS)
91   SIGNAME[SIGBUS]  = "BUS: Bus Error, possibly illegal memory access";
92 #endif
93 #if !defined(PETSC_MISSING_SIGCHLD)
94   SIGNAME[SIGCHLD] = "CHLD";
95 #endif
96 #if !defined(PETSC_MISSING_SIGCONT)
97   SIGNAME[SIGCONT] = "CONT";
98 #endif
99 #if !defined(PETSC_MISSING_SIGFPE)
100   SIGNAME[SIGFPE]  = "FPE: Floating Point Exception,probably divide by zero";
101 #endif
102 #if !defined(PETSC_MISSING_SIGHUP)
103   SIGNAME[SIGHUP]  = "Hang up";
104 #endif
105 #if !defined(PETSC_MISSING_SIGILL)
106   SIGNAME[SIGILL]  = "Illegal instruction";
107 #endif
108 #if !defined(PETSC_MISSING_SIGINT)
109   /*  SIGNAME[SIGINT]  = "Interrupt"; */
110 #endif
111 #if !defined(PETSC_MISSING_SIGKILL)
112   SIGNAME[SIGKILL] = "Kill";
113 #endif
114 #if !defined(PETSC_MISSING_SIGPIPE)
115   SIGNAME[SIGPIPE] = "Broken Pipe";
116 #endif
117 #if !defined(PETSC_MISSING_SIGQUIT)
118   SIGNAME[SIGQUIT] = "Quit";
119 #endif
120 #if !defined(PETSC_MISSING_SIGSEGV)
121   SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range";
122 #endif
123 #if !defined(PETSC_MISSING_SIGSYS)
124   SIGNAME[SIGSYS]  = "SYS";
125 #endif
126 #if !defined(PETSC_MISSING_SIGTERM)
127   /*SIGNAME[SIGTERM] = "Terminate";*/
128 #endif
129 #if !defined(PETSC_MISSING_SIGTRAP)
130   SIGNAME[SIGTRAP] = "TRAP";
131 #endif
132 #if !defined(PETSC_MISSING_SIGTSTP)
133   SIGNAME[SIGTSTP] = "TSTP";
134 #endif
135 #if !defined(PETSC_MISSING_SIGURG)
136   SIGNAME[SIGURG]  = "URG";
137 #endif
138 #if !defined(PETSC_MISSING_SIGUSR1)
139   SIGNAME[SIGUSR1] = "User 1";
140 #endif
141 #if !defined(PETSC_MISSING_SIGUSR2)
142   SIGNAME[SIGUSR2] = "User 2";
143 #endif
144 
145   signal(sig,SIG_DFL);
146   if (sig >= 0 && sig <= 20) {
147     (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
148   } else {
149     (*PetscErrorPrintf)("Caught signal\n");
150   }
151   (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
152 #if defined(PETSC_USE_DEBUG)
153   if (!PetscStackActive) {
154     (*PetscErrorPrintf)("  or try option -log_stack\n");
155   } else {
156     PetscStackPop;  /* remove stack frames for error handlers */
157     PetscStackPop;
158     (*PetscErrorPrintf)("likely location of problem given in stack below\n");
159     (*PetscErrorPrintf)("--------------- Stack Frames ---------------\n");
160     PetscStackView(PETSC_VIEWER_STDOUT_SELF);
161     (*PetscErrorPrintf)("--------------------------------------------\n");
162   }
163 #endif
164 #if !defined(PETSC_USE_DEBUG)
165   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
166   (*PetscErrorPrintf)("to get more information on the crash.\n");
167 #endif
168   ierr =  PetscError(0,"User provided function"," unknown file","unknown directory",PETSC_ERR_SIG,1," ");
169   MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
170   PetscFunctionReturn(0);
171 }
172 
173 #if !defined(PETSC_SIGNAL_CAST)
174 #define PETSC_SIGNAL_CAST
175 #endif
176 
177 #undef __FUNCT__
178 #define __FUNCT__ "PetscPushSignalHandler"
179 /*@C
180    PetscPushSignalHandler - Catches the usual fatal errors and
181    calls a user-provided routine.
182 
183    Not Collective
184 
185     Input Parameter:
186 +  routine - routine to call when a signal is received
187 -  ctx - optional context needed by the routine
188 
189   Level: developer
190 
191    Concepts: signal handler^setting
192 
193 .seealso: PetscPopSignalHandler(), PetscDefaultSignalHandler()
194 
195 @*/
196 PetscErrorCode PETSC_DLLEXPORT PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void* ctx)
197 {
198   struct  SH     *newsh;
199   PetscErrorCode ierr;
200 
201   PetscFunctionBegin;
202   if (!SIGNAL_COOKIE) {
203     ierr = PetscLogClassRegister(&SIGNAL_COOKIE,"Signal");CHKERRQ(ierr);
204   }
205   if (!SignalSet && routine) {
206     /* Do not catch ABRT, CHLD, KILL */
207 #if !defined(PETSC_MISSING_SIGALRM)
208     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
209 #endif
210 #if !defined(PETSC_MISSING_SIGBUS)
211     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
212 #endif
213 #if !defined(PETSC_MISSING_SIGCONT)
214     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
215 #endif
216 #if !defined(PETSC_MISSING_SIGFPE)
217     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
218 #endif
219 #if !defined(PETSC_MISSING_SIGHUP)
220     signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
221 #endif
222 #if !defined(PETSC_MISSING_SIGILL)
223     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
224 #endif
225 #if !defined(PETSC_MISSING_SIGINT)
226     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
227 #endif
228 #if !defined(PETSC_MISSING_SIGPIPE)
229     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
230 #endif
231 #if !defined(PETSC_MISSING_SIGQUIT)
232     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
233 #endif
234 #if !defined(PETSC_MISSING_SIGSEGV)
235     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
236 #endif
237 #if !defined(PETSC_MISSING_SIGSYS)
238     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
239 #endif
240 #if !defined(PETSC_MISSING_SIGTERM)
241     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
242 #endif
243 #if !defined(PETSC_MISSING_SIGTRAP)
244     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
245 #endif
246 #if !defined(PETSC_MISSING_SIGTSTP)
247     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
248 #endif
249 #if !defined(PETSC_MISSING_SIGURG)
250     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
251 #endif
252 #if !defined(PETSC_MISSING_SIGUSR1)
253     /*    signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
254 #endif
255 #if !defined(PETSC_MISSING_SIGUSR2)
256     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
257 #endif
258     SignalSet = PETSC_TRUE;
259   }
260   if (!routine) {
261 #if !defined(PETSC_MISSING_SIGALRM)
262     /* signal(SIGALRM, 0); */
263 #endif
264 #if !defined(PETSC_MISSING_SIGBUS)
265     signal(SIGBUS,  0);
266 #endif
267 #if !defined(PETSC_MISSING_SIGCONT)
268     /* signal(SIGCONT, 0); */
269 #endif
270 #if !defined(PETSC_MISSING_SIGFPE)
271     signal(SIGFPE,  0);
272 #endif
273 #if !defined(PETSC_MISSING_SIGHUP)
274     signal(SIGHUP,  0);
275 #endif
276 #if !defined(PETSC_MISSING_SIGILL)
277     signal(SIGILL,  0);
278 #endif
279 #if !defined(PETSC_MISSING_SIGINT)
280     /* signal(SIGINT,  0); */
281 #endif
282 #if !defined(PETSC_MISSING_SIGPIPE)
283     signal(SIGPIPE, 0);
284 #endif
285 #if !defined(PETSC_MISSING_SIGQUIT)
286     signal(SIGQUIT, 0);
287 #endif
288 #if !defined(PETSC_MISSING_SIGSEGV)
289     signal(SIGSEGV, 0);
290 #endif
291 #if !defined(PETSC_MISSING_SIGSYS)
292     signal(SIGSYS,  0);
293 #endif
294 #if !defined(PETSC_MISSING_SIGTERM)
295     signal(SIGTERM, 0);
296 #endif
297 #if !defined(PETSC_MISSING_SIGTRAP)
298     signal(SIGTRAP, 0);
299 #endif
300 #if !defined(PETSC_MISSING_SIGTSTP)
301     /* signal(SIGTSTP, 0); */
302 #endif
303 #if !defined(PETSC_MISSING_SIGURG)
304     signal(SIGURG,  0);
305 #endif
306 #if !defined(PETSC_MISSING_SIGUSR1)
307     /*    signal(SIGUSR1, 0); */
308 #endif
309 #if !defined(PETSC_MISSING_SIGUSR2)
310     /* signal(SIGUSR2, 0); */
311 #endif
312     SignalSet = PETSC_FALSE;
313   }
314   ierr = PetscNew(struct SH,&newsh);CHKERRQ(ierr);
315   if (sh) {
316     if (sh->cookie != SIGNAL_COOKIE) SETERRQ(PETSC_ERR_COR,"Signal object has been corrupted");
317     newsh->previous = sh;
318   }
319   else {newsh->previous = 0;}
320   newsh->handler = routine;
321   newsh->ctx     = ctx;
322   newsh->cookie  = SIGNAL_COOKIE;
323   sh             = newsh;
324   PetscFunctionReturn(0);
325 }
326 
327 #undef __FUNCT__
328 #define __FUNCT__ "PetscPopSignalHandler"
329 /*@
330    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
331        If no signal handlers are left on the stack it will remove the PETSc signal handler.
332        (That is PETSc will no longer catch signals).
333 
334    Not Collective
335 
336   Level: developer
337 
338    Concepts: signal handler^setting
339 
340 .seealso: PetscPushSignalHandler()
341 
342 @*/
343 PetscErrorCode PETSC_DLLEXPORT PetscPopSignalHandler(void)
344 {
345   struct SH *tmp;
346 
347   PetscFunctionBegin;
348   if (!sh) PetscFunctionReturn(0);
349   if (sh->cookie != SIGNAL_COOKIE) SETERRQ(PETSC_ERR_COR,"Signal object has been corrupted");
350 
351   tmp = sh;
352   sh  = sh->previous;
353   PetscFreeVoid(tmp);
354   if (!sh || !sh->handler) {
355 #if !defined(PETSC_MISSING_SIGALRM)
356     /* signal(SIGALRM, 0); */
357 #endif
358 #if !defined(PETSC_MISSING_SIGBUS)
359     signal(SIGBUS,  0);
360 #endif
361 #if !defined(PETSC_MISSING_SIGCONT)
362     /* signal(SIGCONT, 0); */
363 #endif
364 #if !defined(PETSC_MISSING_SIGFPE)
365     signal(SIGFPE,  0);
366 #endif
367 #if !defined(PETSC_MISSING_SIGHUP)
368     signal(SIGHUP,  0);
369 #endif
370 #if !defined(PETSC_MISSING_SIGILL)
371     signal(SIGILL,  0);
372 #endif
373 #if !defined(PETSC_MISSING_SIGINT)
374     /* signal(SIGINT,  0); */
375 #endif
376 #if !defined(PETSC_MISSING_SIGPIPE)
377     signal(SIGPIPE, 0);
378 #endif
379 #if !defined(PETSC_MISSING_SIGQUIT)
380     signal(SIGQUIT, 0);
381 #endif
382 #if !defined(PETSC_MISSING_SIGSEGV)
383     signal(SIGSEGV, 0);
384 #endif
385 #if !defined(PETSC_MISSING_SIGSYS)
386     signal(SIGSYS,  0);
387 #endif
388 #if !defined(PETSC_MISSING_SIGTERM)
389     signal(SIGTERM, 0);
390 #endif
391 #if !defined(PETSC_MISSING_SIGTRAP)
392     signal(SIGTRAP, 0);
393 #endif
394 #if !defined(PETSC_MISSING_SIGTSTP)
395     /* signal(SIGTSTP, 0); */
396 #endif
397 #if !defined(PETSC_MISSING_SIGURG)
398     signal(SIGURG,  0);
399 #endif
400 #if !defined(PETSC_MISSING_SIGUSR1)
401     /*    signal(SIGUSR1, 0); */
402 #endif
403 #if !defined(PETSC_MISSING_SIGUSR2)
404     /* signal(SIGUSR2, 0); */
405 #endif
406     SignalSet = PETSC_FALSE;
407   } else {
408     SignalSet = PETSC_TRUE;
409   }
410   PetscFunctionReturn(0);
411 }
412 
413 
414 
415 
416