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