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