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