xref: /petsc/src/sys/error/signal.c (revision e5a36eccef3d6b83a2c625c30d0dfd5adb4001f2)
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 http://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)
204     signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
205 #endif
206 #if !defined(PETSC_MISSING_SIGILL)
207     signal(SIGILL,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
208 #endif
209 #if !defined(PETSC_MISSING_SIGINT)
210     /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
211 #endif
212 #if !defined(PETSC_MISSING_SIGPIPE)
213     signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
214 #endif
215 #if !defined(PETSC_MISSING_SIGQUIT)
216     signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
217 #endif
218 #if !defined(PETSC_MISSING_SIGSEGV)
219     signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private);
220 #endif
221 #if !defined(PETSC_MISSING_SIGSYS)
222     signal(SIGSYS,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
223 #endif
224 #if !defined(PETSC_MISSING_SIGTERM)
225     signal(SIGTERM,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
226 #endif
227 #if !defined(PETSC_MISSING_SIGTRAP)
228     signal(SIGTRAP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
229 #endif
230 #if !defined(PETSC_MISSING_SIGTSTP)
231     /* signal(SIGTSTP,  PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
232 #endif
233 #if !defined(PETSC_MISSING_SIGURG)
234     signal(SIGURG,  PETSC_SIGNAL_CAST PetscSignalHandler_Private);
235 #endif
236 #if !defined(PETSC_MISSING_SIGUSR1)
237     /*    signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
238 #endif
239 #if !defined(PETSC_MISSING_SIGUSR2)
240     /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */
241 #endif
242     SignalSet = PETSC_TRUE;
243   }
244   if (!routine) {
245 #if !defined(PETSC_MISSING_SIGALRM)
246     /* signal(SIGALRM, 0); */
247 #endif
248 #if !defined(PETSC_MISSING_SIGBUS)
249     signal(SIGBUS,  0);
250 #endif
251 #if !defined(PETSC_MISSING_SIGCONT)
252     /* signal(SIGCONT, 0); */
253 #endif
254 #if !defined(PETSC_MISSING_SIGFPE)
255     signal(SIGFPE,  0);
256 #endif
257 #if !defined(PETSC_MISSING_SIGHUP)
258     signal(SIGHUP,  0);
259 #endif
260 #if !defined(PETSC_MISSING_SIGILL)
261     signal(SIGILL,  0);
262 #endif
263 #if !defined(PETSC_MISSING_SIGINT)
264     /* signal(SIGINT,  0); */
265 #endif
266 #if !defined(PETSC_MISSING_SIGPIPE)
267     signal(SIGPIPE, 0);
268 #endif
269 #if !defined(PETSC_MISSING_SIGQUIT)
270     signal(SIGQUIT, 0);
271 #endif
272 #if !defined(PETSC_MISSING_SIGSEGV)
273     signal(SIGSEGV, 0);
274 #endif
275 #if !defined(PETSC_MISSING_SIGSYS)
276     signal(SIGSYS,  0);
277 #endif
278 #if !defined(PETSC_MISSING_SIGTERM)
279     signal(SIGTERM, 0);
280 #endif
281 #if !defined(PETSC_MISSING_SIGTRAP)
282     signal(SIGTRAP, 0);
283 #endif
284 #if !defined(PETSC_MISSING_SIGTSTP)
285     /* signal(SIGTSTP, 0); */
286 #endif
287 #if !defined(PETSC_MISSING_SIGURG)
288     signal(SIGURG,  0);
289 #endif
290 #if !defined(PETSC_MISSING_SIGUSR1)
291     /*    signal(SIGUSR1, 0); */
292 #endif
293 #if !defined(PETSC_MISSING_SIGUSR2)
294     /* signal(SIGUSR2, 0); */
295 #endif
296     SignalSet = PETSC_FALSE;
297   }
298   ierr = PetscNew(&newsh);CHKERRQ(ierr);
299   if (sh) {
300     if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
301     newsh->previous = sh;
302   }  else newsh->previous = 0;
303   newsh->handler = routine;
304   newsh->ctx     = ctx;
305   newsh->classid = SIGNAL_CLASSID;
306   sh             = newsh;
307   PetscFunctionReturn(0);
308 }
309 
310 /*@
311    PetscPopSignalHandler - Removes the most last signal handler that was pushed.
312        If no signal handlers are left on the stack it will remove the PETSc signal handler.
313        (That is PETSc will no longer catch signals).
314 
315    Not Collective
316 
317   Level: developer
318 
319    Concepts: signal handler^setting
320 
321 .seealso: PetscPushSignalHandler()
322 
323 @*/
324 PetscErrorCode  PetscPopSignalHandler(void)
325 {
326   struct SH      *tmp;
327   PetscErrorCode ierr;
328 
329   PetscFunctionBegin;
330   if (!sh) PetscFunctionReturn(0);
331   if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted");
332 
333   tmp = sh;
334   sh  = sh->previous;
335   ierr = PetscFree(tmp);CHKERRQ(ierr);
336   if (!sh || !sh->handler) {
337 #if !defined(PETSC_MISSING_SIGALRM)
338     /* signal(SIGALRM, 0); */
339 #endif
340 #if !defined(PETSC_MISSING_SIGBUS)
341     signal(SIGBUS,  0);
342 #endif
343 #if !defined(PETSC_MISSING_SIGCONT)
344     /* signal(SIGCONT, 0); */
345 #endif
346 #if !defined(PETSC_MISSING_SIGFPE)
347     signal(SIGFPE,  0);
348 #endif
349 #if !defined(PETSC_MISSING_SIGHUP)
350     signal(SIGHUP,  0);
351 #endif
352 #if !defined(PETSC_MISSING_SIGILL)
353     signal(SIGILL,  0);
354 #endif
355 #if !defined(PETSC_MISSING_SIGINT)
356     /* signal(SIGINT,  0); */
357 #endif
358 #if !defined(PETSC_MISSING_SIGPIPE)
359     signal(SIGPIPE, 0);
360 #endif
361 #if !defined(PETSC_MISSING_SIGQUIT)
362     signal(SIGQUIT, 0);
363 #endif
364 #if !defined(PETSC_MISSING_SIGSEGV)
365     signal(SIGSEGV, 0);
366 #endif
367 #if !defined(PETSC_MISSING_SIGSYS)
368     signal(SIGSYS,  0);
369 #endif
370 #if !defined(PETSC_MISSING_SIGTERM)
371     signal(SIGTERM, 0);
372 #endif
373 #if !defined(PETSC_MISSING_SIGTRAP)
374     signal(SIGTRAP, 0);
375 #endif
376 #if !defined(PETSC_MISSING_SIGTSTP)
377     /* signal(SIGTSTP, 0); */
378 #endif
379 #if !defined(PETSC_MISSING_SIGURG)
380     signal(SIGURG,  0);
381 #endif
382 #if !defined(PETSC_MISSING_SIGUSR1)
383     /*    signal(SIGUSR1, 0); */
384 #endif
385 #if !defined(PETSC_MISSING_SIGUSR2)
386     /* signal(SIGUSR2, 0); */
387 #endif
388     SignalSet = PETSC_FALSE;
389   } else {
390     SignalSet = PETSC_TRUE;
391   }
392   PetscFunctionReturn(0);
393 }
394