xref: /petsc/src/sys/error/signal.c (revision 2da392cc7c10228af19ad9843ce5155178acb644)
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 (PetscDefined(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   } else {
156     (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n");
157     (*PetscErrorPrintf)("to get more information on the crash.\n");
158   }
159   ierr =  PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL);
160   atexit(MyExit);
161   PETSCABORT(PETSC_COMM_WORLD,(int)ierr);
162   PetscFunctionReturn(0);
163 }
164 
165 #if !defined(PETSC_SIGNAL_CAST)
166 #define PETSC_SIGNAL_CAST
167 #endif
168 
169 /*@C
170    PetscPushSignalHandler - Catches the usual fatal errors and
171    calls a user-provided routine.
172 
173    Not Collective
174 
175     Input Parameter:
176 +  routine - routine to call when a signal is received
177 -  ctx - optional context needed by the routine
178 
179   Level: developer
180 
181 .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler()
182 
183 @*/
184 PetscErrorCode  PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx)
185 {
186   struct  SH     *newsh;
187   PetscErrorCode ierr;
188 
189   PetscFunctionBegin;
190   if (!SIGNAL_CLASSID) {
191     /* ierr = PetscClassIdRegister("Signal",&SIGNAL_CLASSID);CHKERRQ(ierr); */
192     SIGNAL_CLASSID = 19;
193   }
194   if (!SignalSet && routine) {
195     /* Do not catch ABRT, CHLD, KILL */
196 #if !defined(PETSC_MISSING_SIGALRM)
197     /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
198 #endif
199 #if !defined(PETSC_MISSING_SIGBUS)
200     signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
201 #endif
202 #if !defined(PETSC_MISSING_SIGCONT)
203     /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/
204 #endif
205 #if !defined(PETSC_MISSING_SIGFPE)
206     signal(SIGFPE,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
207 #endif
208 #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION)
209     {
210       struct  sigaction action;
211       sigaction(SIGHUP,NULL,&action);
212       if (action.sa_handler == SIG_IGN) {
213         ierr = PetscInfo(NULL,"SIGHUP previously set to ignore, therefor not changing its signal handler\n");CHKERRQ(ierr);
214       } else {
215         signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
216       }
217     }
218 #endif
219 #if !defined(PETSC_MISSING_SIGILL)
220     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
221 #endif
222 #if !defined(PETSC_MISSING_SIGINT)
223     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
224 #endif
225 #if !defined(PETSC_MISSING_SIGPIPE)
226     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
227 #endif
228 #if !defined(PETSC_MISSING_SIGQUIT)
229     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
230 #endif
231 #if !defined(PETSC_MISSING_SIGSEGV)
232     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
233 #endif
234 #if !defined(PETSC_MISSING_SIGSYS)
235     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
236 #endif
237 #if !defined(PETSC_MISSING_SIGTERM)
238     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
239 #endif
240 #if !defined(PETSC_MISSING_SIGTRAP)
241     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
242 #endif
243 #if !defined(PETSC_MISSING_SIGTSTP)
244     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
245 #endif
246 #if !defined(PETSC_MISSING_SIGURG)
247     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
248 #endif
249 #if !defined(PETSC_MISSING_SIGUSR1)
250     /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
251 #endif
252 #if !defined(PETSC_MISSING_SIGUSR2)
253     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
254 #endif
255     SignalSet = PETSC_TRUE;
256   }
257   if (!routine) {
258 #if !defined(PETSC_MISSING_SIGALRM)
259     /* signal(SIGALRM, SIG_DFL); */
260 #endif
261 #if !defined(PETSC_MISSING_SIGBUS)
262     signal(SIGBUS,  SIG_DFL);
263 #endif
264 #if !defined(PETSC_MISSING_SIGCONT)
265     /* signal(SIGCONT, SIG_DFL); */
266 #endif
267 #if !defined(PETSC_MISSING_SIGFPE)
268     signal(SIGFPE,  SIG_DFL);
269 #endif
270 #if !defined(PETSC_MISSING_SIGHUP)
271     signal(SIGHUP,  SIG_DFL);
272 #endif
273 #if !defined(PETSC_MISSING_SIGILL)
274     signal(SIGILL,  SIG_DFL);
275 #endif
276 #if !defined(PETSC_MISSING_SIGINT)
277     /* signal(SIGINT,  SIG_DFL); */
278 #endif
279 #if !defined(PETSC_MISSING_SIGPIPE)
280     signal(SIGPIPE, SIG_DFL);
281 #endif
282 #if !defined(PETSC_MISSING_SIGQUIT)
283     signal(SIGQUIT, SIG_DFL);
284 #endif
285 #if !defined(PETSC_MISSING_SIGSEGV)
286     signal(SIGSEGV, SIG_DFL);
287 #endif
288 #if !defined(PETSC_MISSING_SIGSYS)
289     signal(SIGSYS,  SIG_DFL);
290 #endif
291 #if !defined(PETSC_MISSING_SIGTERM)
292     signal(SIGTERM, SIG_DFL);
293 #endif
294 #if !defined(PETSC_MISSING_SIGTRAP)
295     signal(SIGTRAP, SIG_DFL);
296 #endif
297 #if !defined(PETSC_MISSING_SIGTSTP)
298     /* signal(SIGTSTP, SIG_DFL); */
299 #endif
300 #if !defined(PETSC_MISSING_SIGURG)
301     signal(SIGURG,  SIG_DFL);
302 #endif
303 #if !defined(PETSC_MISSING_SIGUSR1)
304     /* signal(SIGUSR1, SIG_DFL); */
305 #endif
306 #if !defined(PETSC_MISSING_SIGUSR2)
307     /* signal(SIGUSR2, SIG_DFL); */
308 #endif
309     SignalSet = PETSC_FALSE;
310   }
311   ierr = PetscNew(&newsh);CHKERRQ(ierr);
312   if (sh) {
313     if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
314     newsh->previous = sh;
315   }  else newsh->previous = NULL;
316   newsh->handler = routine;
317   newsh->ctx     = ctx;
318   newsh->classid = SIGNAL_CLASSID;
319   sh             = newsh;
320   PetscFunctionReturn(0);
321 }
322 
323 /*@
324    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
325        If no signal handlers are left on the stack it will remove the PETSc signal handler.
326        (That is PETSc will no longer catch signals).
327 
328    Not Collective
329 
330   Level: developer
331 
332 .seealso: PetscPushSignalHandler()
333 
334 @*/
335 PetscErrorCode  PetscPopSignalHandler(void)
336 {
337   struct SH      *tmp;
338   PetscErrorCode ierr;
339 
340   PetscFunctionBegin;
341   if (!sh) PetscFunctionReturn(0);
342   if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
343 
344   tmp = sh;
345   sh  = sh->previous;
346   ierr = PetscFree(tmp);CHKERRQ(ierr);
347   if (!sh || !sh->handler) {
348 #if !defined(PETSC_MISSING_SIGALRM)
349     /* signal(SIGALRM, SIG_DFL); */
350 #endif
351 #if !defined(PETSC_MISSING_SIGBUS)
352     signal(SIGBUS,  SIG_DFL);
353 #endif
354 #if !defined(PETSC_MISSING_SIGCONT)
355     /* signal(SIGCONT, SIG_DFL); */
356 #endif
357 #if !defined(PETSC_MISSING_SIGFPE)
358     signal(SIGFPE,  SIG_DFL);
359 #endif
360 #if !defined(PETSC_MISSING_SIGHUP)
361     signal(SIGHUP,  SIG_DFL);
362 #endif
363 #if !defined(PETSC_MISSING_SIGILL)
364     signal(SIGILL,  SIG_DFL);
365 #endif
366 #if !defined(PETSC_MISSING_SIGINT)
367     /* signal(SIGINT,  SIG_DFL); */
368 #endif
369 #if !defined(PETSC_MISSING_SIGPIPE)
370     signal(SIGPIPE, SIG_DFL);
371 #endif
372 #if !defined(PETSC_MISSING_SIGQUIT)
373     signal(SIGQUIT, SIG_DFL);
374 #endif
375 #if !defined(PETSC_MISSING_SIGSEGV)
376     signal(SIGSEGV, SIG_DFL);
377 #endif
378 #if !defined(PETSC_MISSING_SIGSYS)
379     signal(SIGSYS,  SIG_DFL);
380 #endif
381 #if !defined(PETSC_MISSING_SIGTERM)
382     signal(SIGTERM, SIG_DFL);
383 #endif
384 #if !defined(PETSC_MISSING_SIGTRAP)
385     signal(SIGTRAP, SIG_DFL);
386 #endif
387 #if !defined(PETSC_MISSING_SIGTSTP)
388     /* signal(SIGTSTP, SIG_DFL); */
389 #endif
390 #if !defined(PETSC_MISSING_SIGURG)
391     signal(SIGURG,  SIG_DFL);
392 #endif
393 #if !defined(PETSC_MISSING_SIGUSR1)
394     /* signal(SIGUSR1, SIG_DFL); */
395 #endif
396 #if !defined(PETSC_MISSING_SIGUSR2)
397     /* signal(SIGUSR2, SIG_DFL); */
398 #endif
399     SignalSet = PETSC_FALSE;
400   } else {
401     SignalSet = PETSC_TRUE;
402   }
403   PetscFunctionReturn(0);
404 }
405