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