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