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