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