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