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