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