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