xref: /petsc/src/sys/error/signal.c (revision 5ab1ac2bae2c53bf5666daef2efaf6cb34bd2dd4)
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 #include <stdlib.h> /* for _Exit() */
9 
10 static PetscClassId SIGNAL_CLASSID = 0;
11 
12 struct SH {
13   PetscClassId   classid;
14   PetscErrorCode (*handler)(int,void*);
15   void           *ctx;
16   struct SH      *previous;
17 };
18 static struct SH *sh       = NULL;
19 static PetscBool SignalSet = PETSC_FALSE;
20 
21 /* Called by MPI_Abort() to suppress user-registered atexit()/on_exit() functions.
22    See discussion at https://gitlab.com/petsc/petsc/-/merge_requests/2745.
23 */
24 static void MyExit(void)
25 {
26   _Exit(MPI_ERR_OTHER);
27 }
28 
29 /*
30     PetscSignalHandler_Private - This is the signal handler called by the system. This calls
31              any signal handler set by PETSc or the application code.
32 
33    Input Parameters: (depends on system)
34 .    sig - integer code indicating the type of signal
35 .    code - ??
36 .    sigcontext - ??
37 .    addr - ??
38 
39 */
40 #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER)
41 static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr)
42 #else
43 static void PetscSignalHandler_Private(int sig)
44 #endif
45 {
46   PetscErrorCode ierr;
47 
48   PetscFunctionBegin;
49   if (!sh || !sh->handler) ierr = PetscSignalHandlerDefault(sig,(void*)0);
50   else {
51     if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted");
52     ierr = (*sh->handler)(sig,sh->ctx);
53   }
54   if (ierr) PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_COR);
55 }
56 
57 /*@
58    PetscSignalHandlerDefault - Default signal handler.
59 
60    Not Collective
61 
62    Level: advanced
63 
64    Input Parameters:
65 +  sig - signal value
66 -  ptr - unused pointer
67 
68 @*/
69 PetscErrorCode  PetscSignalHandlerDefault(int sig,void *ptr)
70 {
71   PetscErrorCode ierr;
72   const char     *SIGNAME[64];
73 
74   PetscFunctionBegin;
75   if (sig == SIGSEGV) PetscSignalSegvCheckPointerOrMpi();
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: Some 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 https://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n");
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",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
161   atexit(MyExit);
162   PETSCABORT(PETSC_COMM_WORLD,(int)ierr);
163   PetscFunctionReturn(0);
164 }
165 
166 #if !defined(PETSC_SIGNAL_CAST)
167 #define PETSC_SIGNAL_CAST
168 #endif
169 
170 /*@C
171    PetscPushSignalHandler - Catches the usual fatal errors and
172    calls a user-provided routine.
173 
174    Not Collective
175 
176     Input Parameter:
177 +  routine - routine to call when a signal is received
178 -  ctx - optional context needed by the routine
179 
180   Level: developer
181 
182 .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()
183 
184 @*/
185 PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
186 {
187   struct  SH     *newsh;
188   PetscErrorCode ierr;
189 
190   PetscFunctionBegin;
191   if (!SIGNAL_CLASSID) {
192     /* ierr = PetscClassIdRegister("Signal",&SIGNAL_CLASSID);CHKERRQ(ierr); */
193     SIGNAL_CLASSID = 19;
194   }
195   if (!SignalSet && routine) {
196     /* Do not catch ABRT, CHLD, KILL */
197 #if !defined(PETSC_MISSING_SIGALRM)
198     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
199 #endif
200 #if !defined(PETSC_MISSING_SIGBUS)
201     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
202 #endif
203 #if !defined(PETSC_MISSING_SIGCONT)
204     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
205 #endif
206 #if !defined(PETSC_MISSING_SIGFPE)
207     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
208 #endif
209 #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION)
210     {
211       struct  sigaction action;
212       sigaction(SIGHUP,NULL,&action);
213       if (action.sa_handler == SIG_IGN) {
214         ierr = PetscInfo(NULL,"SIGHUP previously set to ignore, therefor not changing its signal handler\n");CHKERRQ(ierr);
215       } else {
216         signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
217       }
218     }
219 #endif
220 #if !defined(PETSC_MISSING_SIGILL)
221     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
222 #endif
223 #if !defined(PETSC_MISSING_SIGINT)
224     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
225 #endif
226 #if !defined(PETSC_MISSING_SIGPIPE)
227     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
228 #endif
229 #if !defined(PETSC_MISSING_SIGQUIT)
230     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
231 #endif
232 #if !defined(PETSC_MISSING_SIGSEGV)
233     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
234 #endif
235 #if !defined(PETSC_MISSING_SIGSYS)
236     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
237 #endif
238 #if !defined(PETSC_MISSING_SIGTERM)
239     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
240 #endif
241 #if !defined(PETSC_MISSING_SIGTRAP)
242     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
243 #endif
244 #if !defined(PETSC_MISSING_SIGTSTP)
245     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
246 #endif
247 #if !defined(PETSC_MISSING_SIGURG)
248     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
249 #endif
250 #if !defined(PETSC_MISSING_SIGUSR1)
251     /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
252 #endif
253 #if !defined(PETSC_MISSING_SIGUSR2)
254     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
255 #endif
256     SignalSet = PETSC_TRUE;
257   }
258   if (!routine) {
259 #if !defined(PETSC_MISSING_SIGALRM)
260     /* signal(SIGALRM, SIG_DFL); */
261 #endif
262 #if !defined(PETSC_MISSING_SIGBUS)
263     signal(SIGBUS,  SIG_DFL);
264 #endif
265 #if !defined(PETSC_MISSING_SIGCONT)
266     /* signal(SIGCONT, SIG_DFL); */
267 #endif
268 #if !defined(PETSC_MISSING_SIGFPE)
269     signal(SIGFPE,  SIG_DFL);
270 #endif
271 #if !defined(PETSC_MISSING_SIGHUP)
272     signal(SIGHUP,  SIG_DFL);
273 #endif
274 #if !defined(PETSC_MISSING_SIGILL)
275     signal(SIGILL,  SIG_DFL);
276 #endif
277 #if !defined(PETSC_MISSING_SIGINT)
278     /* signal(SIGINT,  SIG_DFL); */
279 #endif
280 #if !defined(PETSC_MISSING_SIGPIPE)
281     signal(SIGPIPE, SIG_DFL);
282 #endif
283 #if !defined(PETSC_MISSING_SIGQUIT)
284     signal(SIGQUIT, SIG_DFL);
285 #endif
286 #if !defined(PETSC_MISSING_SIGSEGV)
287     signal(SIGSEGV, SIG_DFL);
288 #endif
289 #if !defined(PETSC_MISSING_SIGSYS)
290     signal(SIGSYS,  SIG_DFL);
291 #endif
292 #if !defined(PETSC_MISSING_SIGTERM)
293     signal(SIGTERM, SIG_DFL);
294 #endif
295 #if !defined(PETSC_MISSING_SIGTRAP)
296     signal(SIGTRAP, SIG_DFL);
297 #endif
298 #if !defined(PETSC_MISSING_SIGTSTP)
299     /* signal(SIGTSTP, SIG_DFL); */
300 #endif
301 #if !defined(PETSC_MISSING_SIGURG)
302     signal(SIGURG,  SIG_DFL);
303 #endif
304 #if !defined(PETSC_MISSING_SIGUSR1)
305     /* signal(SIGUSR1, SIG_DFL); */
306 #endif
307 #if !defined(PETSC_MISSING_SIGUSR2)
308     /* signal(SIGUSR2, SIG_DFL); */
309 #endif
310     SignalSet = PETSC_FALSE;
311   }
312   ierr = PetscNew(&newsh);CHKERRQ(ierr);
313   if (sh) {
314     if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
315     newsh->previous = sh;
316   }  else newsh->previous = NULL;
317   newsh->handler = routine;
318   newsh->ctx     = ctx;
319   newsh->classid = SIGNAL_CLASSID;
320   sh             = newsh;
321   PetscFunctionReturn(0);
322 }
323 
324 /*@
325    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
326        If no signal handlers are left on the stack it will remove the PETSc signal handler.
327        (That is PETSc will no longer catch signals).
328 
329    Not Collective
330 
331   Level: developer
332 
333 .seealso: PetscPushSignalHandler()
334 
335 @*/
336 PetscErrorCode  PetscPopSignalHandler(void)
337 {
338   struct SH      *tmp;
339   PetscErrorCode ierr;
340 
341   PetscFunctionBegin;
342   if (!sh) PetscFunctionReturn(0);
343   if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
344 
345   tmp = sh;
346   sh  = sh->previous;
347   ierr = PetscFree(tmp);CHKERRQ(ierr);
348   if (!sh || !sh->handler) {
349 #if !defined(PETSC_MISSING_SIGALRM)
350     /* signal(SIGALRM, SIG_DFL); */
351 #endif
352 #if !defined(PETSC_MISSING_SIGBUS)
353     signal(SIGBUS,  SIG_DFL);
354 #endif
355 #if !defined(PETSC_MISSING_SIGCONT)
356     /* signal(SIGCONT, SIG_DFL); */
357 #endif
358 #if !defined(PETSC_MISSING_SIGFPE)
359     signal(SIGFPE,  SIG_DFL);
360 #endif
361 #if !defined(PETSC_MISSING_SIGHUP)
362     signal(SIGHUP,  SIG_DFL);
363 #endif
364 #if !defined(PETSC_MISSING_SIGILL)
365     signal(SIGILL,  SIG_DFL);
366 #endif
367 #if !defined(PETSC_MISSING_SIGINT)
368     /* signal(SIGINT,  SIG_DFL); */
369 #endif
370 #if !defined(PETSC_MISSING_SIGPIPE)
371     signal(SIGPIPE, SIG_DFL);
372 #endif
373 #if !defined(PETSC_MISSING_SIGQUIT)
374     signal(SIGQUIT, SIG_DFL);
375 #endif
376 #if !defined(PETSC_MISSING_SIGSEGV)
377     signal(SIGSEGV, SIG_DFL);
378 #endif
379 #if !defined(PETSC_MISSING_SIGSYS)
380     signal(SIGSYS,  SIG_DFL);
381 #endif
382 #if !defined(PETSC_MISSING_SIGTERM)
383     signal(SIGTERM, SIG_DFL);
384 #endif
385 #if !defined(PETSC_MISSING_SIGTRAP)
386     signal(SIGTRAP, SIG_DFL);
387 #endif
388 #if !defined(PETSC_MISSING_SIGTSTP)
389     /* signal(SIGTSTP, SIG_DFL); */
390 #endif
391 #if !defined(PETSC_MISSING_SIGURG)
392     signal(SIGURG,  SIG_DFL);
393 #endif
394 #if !defined(PETSC_MISSING_SIGUSR1)
395     /* signal(SIGUSR1, SIG_DFL); */
396 #endif
397 #if !defined(PETSC_MISSING_SIGUSR2)
398     /* signal(SIGUSR2, SIG_DFL); */
399 #endif
400     SignalSet = PETSC_FALSE;
401   } else {
402     SignalSet = PETSC_TRUE;
403   }
404   PetscFunctionReturn(0);
405 }
406