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