xref: /petsc/src/sys/error/signal.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
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 "petsc.h"             /*I   "petsc.h"   I*/
7 #include <signal.h>
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: Some other process (or the batch system) has told this process to end";
104 #endif
105 #if !defined(PETSC_MISSING_SIGILL)
106   SIGNAME[SIGILL]  = "Illegal instruction: Likely due to memory corruption";
107 #endif
108 #if !defined(PETSC_MISSING_SIGINT)
109   SIGNAME[SIGINT]  = "Interrupt";
110 #endif
111 #if !defined(PETSC_MISSING_SIGKILL)
112   SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end";
113 #endif
114 #if !defined(PETSC_MISSING_SIGPIPE)
115   SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket";
116 #endif
117 #if !defined(PETSC_MISSING_SIGQUIT)
118   SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end";
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: Somet process (or the batch system) has told this process to end";
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     (*PetscErrorPrintf)("------------------------------------------------------------------------\n");
147   if (sig >= 0 && sig <= 20) {
148     (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]);
149   } else {
150     (*PetscErrorPrintf)("Caught signal\n");
151   }
152   (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n");
153   (*PetscErrorPrintf)("or see http://www.mcs.anl.gov/petsc/petsc-as/documentation/troubleshooting.html#Signal");
154   (*PetscErrorPrintf)("or try http://valgrind.org on linux or man libgmalloc on Apple to find memory corruption errors\n");
155 #if defined(PETSC_USE_DEBUG)
156   if (!PetscStackActive) {
157     (*PetscErrorPrintf)("  or try option -log_stack\n");
158   } else {
159     PetscStackPop;  /* remove stack frames for error handlers */
160     PetscStackPop;
161     (*PetscErrorPrintf)("likely location of problem given in stack below\n");
162     (*PetscErrorPrintf)("---------------------  Stack Frames ------------------------------------\n");
163     PetscStackView(PETSC_VIEWER_STDOUT_SELF);
164   }
165 #endif
166 #if !defined(PETSC_USE_DEBUG)
167   (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
168   (*PetscErrorPrintf)("to get more information on the crash.\n");
169 #endif
170   ierr =  PetscError(0,"User provided function"," unknown file","unknown directory",PETSC_ERR_SIG,1,PETSC_NULL);
171   MPI_Abort(PETSC_COMM_WORLD,(int)ierr);
172   PetscFunctionReturn(0);
173 }
174 
175 #if !defined(PETSC_SIGNAL_CAST)
176 #define PETSC_SIGNAL_CAST
177 #endif
178 
179 #undef __FUNCT__
180 #define __FUNCT__ "PetscPushSignalHandler"
181 /*@C
182    PetscPushSignalHandler - Catches the usual fatal errors and
183    calls a user-provided routine.
184 
185    Not Collective
186 
187     Input Parameter:
188 +  routine - routine to call when a signal is received
189 -  ctx - optional context needed by the routine
190 
191   Level: developer
192 
193    Concepts: signal handler^setting
194 
195 .seealso: PetscPopSignalHandler(), PetscDefaultSignalHandler()
196 
197 @*/
198 PetscErrorCode PETSC_DLLEXPORT PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void* ctx)
199 {
200   struct  SH     *newsh;
201   PetscErrorCode ierr;
202 
203   PetscFunctionBegin;
204   if (!SIGNAL_COOKIE) {
205     /* ierr = PetscLogClassRegister(&SIGNAL_COOKIE,"Signal");CHKERRQ(ierr); */
206     SIGNAL_COOKIE = 19;
207   }
208   if (!SignalSet && routine) {
209     /* Do not catch ABRT, CHLD, KILL */
210 #if !defined(PETSC_MISSING_SIGALRM)
211     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
212 #endif
213 #if !defined(PETSC_MISSING_SIGBUS)
214     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
215 #endif
216 #if !defined(PETSC_MISSING_SIGCONT)
217     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
218 #endif
219 #if !defined(PETSC_MISSING_SIGFPE)
220     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
221 #endif
222 #if !defined(PETSC_MISSING_SIGHUP)
223     signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
224 #endif
225 #if !defined(PETSC_MISSING_SIGILL)
226     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
227 #endif
228 #if !defined(PETSC_MISSING_SIGINT)
229     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
230 #endif
231 #if !defined(PETSC_MISSING_SIGPIPE)
232     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
233 #endif
234 #if !defined(PETSC_MISSING_SIGQUIT)
235     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
236 #endif
237 #if !defined(PETSC_MISSING_SIGSEGV)
238     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
239 #endif
240 #if !defined(PETSC_MISSING_SIGSYS)
241     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
242 #endif
243 #if !defined(PETSC_MISSING_SIGTERM)
244     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
245 #endif
246 #if !defined(PETSC_MISSING_SIGTRAP)
247     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
248 #endif
249 #if !defined(PETSC_MISSING_SIGTSTP)
250     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
251 #endif
252 #if !defined(PETSC_MISSING_SIGURG)
253     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
254 #endif
255 #if !defined(PETSC_MISSING_SIGUSR1)
256     /*    signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
257 #endif
258 #if !defined(PETSC_MISSING_SIGUSR2)
259     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
260 #endif
261     SignalSet = PETSC_TRUE;
262   }
263   if (!routine) {
264 #if !defined(PETSC_MISSING_SIGALRM)
265     /* signal(SIGALRM, 0); */
266 #endif
267 #if !defined(PETSC_MISSING_SIGBUS)
268     signal(SIGBUS,  0);
269 #endif
270 #if !defined(PETSC_MISSING_SIGCONT)
271     /* signal(SIGCONT, 0); */
272 #endif
273 #if !defined(PETSC_MISSING_SIGFPE)
274     signal(SIGFPE,  0);
275 #endif
276 #if !defined(PETSC_MISSING_SIGHUP)
277     signal(SIGHUP,  0);
278 #endif
279 #if !defined(PETSC_MISSING_SIGILL)
280     signal(SIGILL,  0);
281 #endif
282 #if !defined(PETSC_MISSING_SIGINT)
283     /* signal(SIGINT,  0); */
284 #endif
285 #if !defined(PETSC_MISSING_SIGPIPE)
286     signal(SIGPIPE, 0);
287 #endif
288 #if !defined(PETSC_MISSING_SIGQUIT)
289     signal(SIGQUIT, 0);
290 #endif
291 #if !defined(PETSC_MISSING_SIGSEGV)
292     signal(SIGSEGV, 0);
293 #endif
294 #if !defined(PETSC_MISSING_SIGSYS)
295     signal(SIGSYS,  0);
296 #endif
297 #if !defined(PETSC_MISSING_SIGTERM)
298     signal(SIGTERM, 0);
299 #endif
300 #if !defined(PETSC_MISSING_SIGTRAP)
301     signal(SIGTRAP, 0);
302 #endif
303 #if !defined(PETSC_MISSING_SIGTSTP)
304     /* signal(SIGTSTP, 0); */
305 #endif
306 #if !defined(PETSC_MISSING_SIGURG)
307     signal(SIGURG,  0);
308 #endif
309 #if !defined(PETSC_MISSING_SIGUSR1)
310     /*    signal(SIGUSR1, 0); */
311 #endif
312 #if !defined(PETSC_MISSING_SIGUSR2)
313     /* signal(SIGUSR2, 0); */
314 #endif
315     SignalSet = PETSC_FALSE;
316   }
317   ierr = PetscNew(struct SH,&newsh);CHKERRQ(ierr);
318   if (sh) {
319     if (sh->cookie != SIGNAL_COOKIE) SETERRQ(PETSC_ERR_COR,"Signal object has been corrupted");
320     newsh->previous = sh;
321   }
322   else {newsh->previous = 0;}
323   newsh->handler = routine;
324   newsh->ctx     = ctx;
325   newsh->cookie  = SIGNAL_COOKIE;
326   sh             = newsh;
327   PetscFunctionReturn(0);
328 }
329 
330 #undef __FUNCT__
331 #define __FUNCT__ "PetscPopSignalHandler"
332 /*@
333    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
334        If no signal handlers are left on the stack it will remove the PETSc signal handler.
335        (That is PETSc will no longer catch signals).
336 
337    Not Collective
338 
339   Level: developer
340 
341    Concepts: signal handler^setting
342 
343 .seealso: PetscPushSignalHandler()
344 
345 @*/
346 PetscErrorCode PETSC_DLLEXPORT PetscPopSignalHandler(void)
347 {
348   struct SH *tmp;
349 
350   PetscFunctionBegin;
351   if (!sh) PetscFunctionReturn(0);
352   if (sh->cookie != SIGNAL_COOKIE) SETERRQ(PETSC_ERR_COR,"Signal object has been corrupted");
353 
354   tmp = sh;
355   sh  = sh->previous;
356   PetscFreeVoid(tmp);
357   if (!sh || !sh->handler) {
358 #if !defined(PETSC_MISSING_SIGALRM)
359     /* signal(SIGALRM, 0); */
360 #endif
361 #if !defined(PETSC_MISSING_SIGBUS)
362     signal(SIGBUS,  0);
363 #endif
364 #if !defined(PETSC_MISSING_SIGCONT)
365     /* signal(SIGCONT, 0); */
366 #endif
367 #if !defined(PETSC_MISSING_SIGFPE)
368     signal(SIGFPE,  0);
369 #endif
370 #if !defined(PETSC_MISSING_SIGHUP)
371     signal(SIGHUP,  0);
372 #endif
373 #if !defined(PETSC_MISSING_SIGILL)
374     signal(SIGILL,  0);
375 #endif
376 #if !defined(PETSC_MISSING_SIGINT)
377     /* signal(SIGINT,  0); */
378 #endif
379 #if !defined(PETSC_MISSING_SIGPIPE)
380     signal(SIGPIPE, 0);
381 #endif
382 #if !defined(PETSC_MISSING_SIGQUIT)
383     signal(SIGQUIT, 0);
384 #endif
385 #if !defined(PETSC_MISSING_SIGSEGV)
386     signal(SIGSEGV, 0);
387 #endif
388 #if !defined(PETSC_MISSING_SIGSYS)
389     signal(SIGSYS,  0);
390 #endif
391 #if !defined(PETSC_MISSING_SIGTERM)
392     signal(SIGTERM, 0);
393 #endif
394 #if !defined(PETSC_MISSING_SIGTRAP)
395     signal(SIGTRAP, 0);
396 #endif
397 #if !defined(PETSC_MISSING_SIGTSTP)
398     /* signal(SIGTSTP, 0); */
399 #endif
400 #if !defined(PETSC_MISSING_SIGURG)
401     signal(SIGURG,  0);
402 #endif
403 #if !defined(PETSC_MISSING_SIGUSR1)
404     /*    signal(SIGUSR1, 0); */
405 #endif
406 #if !defined(PETSC_MISSING_SIGUSR2)
407     /* signal(SIGUSR2, 0); */
408 #endif
409     SignalSet = PETSC_FALSE;
410   } else {
411     SignalSet = PETSC_TRUE;
412   }
413   PetscFunctionReturn(0);
414 }
415 
416 
417 
418 
419