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