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