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