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 9 static PetscClassId SIGNAL_CLASSID = 0; 10 11 struct SH { 12 PetscClassId classid; 13 PetscErrorCode (*handler)(int,void*); 14 void *ctx; 15 struct SH *previous; 16 }; 17 static struct SH *sh = NULL; 18 static PetscBool SignalSet = PETSC_FALSE; 19 20 /* 21 PetscSignalHandler_Private - This is the signal handler called by the system. This calls 22 any signal handler set by PETSc or the application code. 23 24 Input Parameters: (depends on system) 25 . sig - integer code indicating the type of signal 26 . code - ?? 27 . sigcontext - ?? 28 . addr - ?? 29 30 */ 31 #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER) 32 static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr) 33 #else 34 static void PetscSignalHandler_Private(int sig) 35 #endif 36 { 37 PetscErrorCode ierr; 38 39 PetscFunctionBegin; 40 if (!sh || !sh->handler) ierr = PetscSignalHandlerDefault(sig,(void*)0); 41 else { 42 if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted"); 43 ierr = (*sh->handler)(sig,sh->ctx); 44 } 45 if (ierr) PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_COR); 46 } 47 48 /*@ 49 PetscSignalHandlerDefault - Default signal handler. 50 51 Not Collective 52 53 Level: advanced 54 55 Input Parameters: 56 + sig - signal value 57 - ptr - unused pointer 58 59 @*/ 60 PetscErrorCode PetscSignalHandlerDefault(int sig,void *ptr) 61 { 62 PetscErrorCode ierr; 63 const char *SIGNAME[64]; 64 65 PetscFunctionBegin; 66 if (sig == SIGSEGV) PetscSignalSegvCheckPointerOrMpi(); 67 SIGNAME[0] = "Unknown signal"; 68 #if !defined(PETSC_MISSING_SIGABRT) 69 SIGNAME[SIGABRT] = "Abort"; 70 #endif 71 #if !defined(PETSC_MISSING_SIGALRM) 72 SIGNAME[SIGALRM] = "Alarm"; 73 #endif 74 #if !defined(PETSC_MISSING_SIGBUS) 75 SIGNAME[SIGBUS] = "BUS: Bus Error, possibly illegal memory access"; 76 #endif 77 #if !defined(PETSC_MISSING_SIGCHLD) 78 SIGNAME[SIGCHLD] = "CHLD"; 79 #endif 80 #if !defined(PETSC_MISSING_SIGCONT) 81 SIGNAME[SIGCONT] = "CONT"; 82 #endif 83 #if !defined(PETSC_MISSING_SIGFPE) 84 SIGNAME[SIGFPE] = "FPE: Floating Point Exception,probably divide by zero"; 85 #endif 86 #if !defined(PETSC_MISSING_SIGHUP) 87 SIGNAME[SIGHUP] = "Hang up: Some other process (or the batch system) has told this process to end"; 88 #endif 89 #if !defined(PETSC_MISSING_SIGILL) 90 SIGNAME[SIGILL] = "Illegal instruction: Likely due to memory corruption"; 91 #endif 92 #if !defined(PETSC_MISSING_SIGINT) 93 SIGNAME[SIGINT] = "Interrupt"; 94 #endif 95 #if !defined(PETSC_MISSING_SIGKILL) 96 SIGNAME[SIGKILL] = "Kill: Some other process (or the batch system) has told this process to end"; 97 #endif 98 #if !defined(PETSC_MISSING_SIGPIPE) 99 SIGNAME[SIGPIPE] = "Broken Pipe: Likely while reading or writing to a socket"; 100 #endif 101 #if !defined(PETSC_MISSING_SIGQUIT) 102 SIGNAME[SIGQUIT] = "Quit: Some other process (or the batch system) has told this process to end"; 103 #endif 104 #if !defined(PETSC_MISSING_SIGSEGV) 105 SIGNAME[SIGSEGV] = "SEGV: Segmentation Violation, probably memory access out of range"; 106 #endif 107 #if !defined(PETSC_MISSING_SIGSYS) 108 SIGNAME[SIGSYS] = "SYS"; 109 #endif 110 #if !defined(PETSC_MISSING_SIGTERM) 111 SIGNAME[SIGTERM] = "Terminate: Some process (or the batch system) has told this process to end"; 112 #endif 113 #if !defined(PETSC_MISSING_SIGTRAP) 114 SIGNAME[SIGTRAP] = "TRAP"; 115 #endif 116 #if !defined(PETSC_MISSING_SIGTSTP) 117 SIGNAME[SIGTSTP] = "TSTP"; 118 #endif 119 #if !defined(PETSC_MISSING_SIGURG) 120 SIGNAME[SIGURG] = "URG"; 121 #endif 122 #if !defined(PETSC_MISSING_SIGUSR1) 123 SIGNAME[SIGUSR1] = "User 1"; 124 #endif 125 #if !defined(PETSC_MISSING_SIGUSR2) 126 SIGNAME[SIGUSR2] = "User 2"; 127 #endif 128 129 signal(sig,SIG_DFL); 130 (*PetscErrorPrintf)("------------------------------------------------------------------------\n"); 131 if (sig >= 0 && sig <= 20) (*PetscErrorPrintf)("Caught signal number %d %s\n",sig,SIGNAME[sig]); 132 else (*PetscErrorPrintf)("Caught signal\n"); 133 134 (*PetscErrorPrintf)("Try option -start_in_debugger or -on_error_attach_debugger\n"); 135 (*PetscErrorPrintf)("or see https://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind\n"); 136 (*PetscErrorPrintf)("or try http://valgrind.org on GNU/linux and Apple Mac OS X to find memory corruption errors\n"); 137 if (PetscDefined(USE_DEBUG)) { 138 if (!PetscStackActive()) (*PetscErrorPrintf)(" or try option -log_stack\n"); 139 else { 140 PetscStackPop; /* remove stack frames for error handlers */ 141 PetscStackPop; 142 (*PetscErrorPrintf)("likely location of problem given in stack below\n"); 143 (*PetscErrorPrintf)("--------------------- Stack Frames ------------------------------------\n"); 144 PetscStackView(PETSC_STDOUT); 145 } 146 } else { 147 (*PetscErrorPrintf)("configure using --with-debugging=yes, recompile, link, and run \n"); 148 (*PetscErrorPrintf)("to get more information on the crash.\n"); 149 } 150 ierr = PetscError(PETSC_COMM_SELF,0,"User provided function"," unknown file",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL); 151 PETSCABORT(PETSC_COMM_WORLD,(int)ierr); 152 PetscFunctionReturn(0); 153 } 154 155 #if !defined(PETSC_SIGNAL_CAST) 156 #define PETSC_SIGNAL_CAST 157 #endif 158 159 /*@C 160 PetscPushSignalHandler - Catches the usual fatal errors and 161 calls a user-provided routine. 162 163 Not Collective 164 165 Input Parameter: 166 + routine - routine to call when a signal is received 167 - ctx - optional context needed by the routine 168 169 Level: developer 170 171 .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler() 172 173 @*/ 174 PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx) 175 { 176 struct SH *newsh; 177 PetscErrorCode ierr; 178 179 PetscFunctionBegin; 180 if (!SIGNAL_CLASSID) { 181 /* ierr = PetscClassIdRegister("Signal",&SIGNAL_CLASSID);CHKERRQ(ierr); */ 182 SIGNAL_CLASSID = 19; 183 } 184 if (!SignalSet && routine) { 185 /* Do not catch ABRT, CHLD, KILL */ 186 #if !defined(PETSC_MISSING_SIGALRM) 187 /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 188 #endif 189 #if !defined(PETSC_MISSING_SIGBUS) 190 signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 191 #endif 192 #if !defined(PETSC_MISSING_SIGCONT) 193 /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/ 194 #endif 195 #if !defined(PETSC_MISSING_SIGFPE) 196 signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 197 #endif 198 #if !defined(PETSC_MISSING_SIGHUP) && defined(PETSC_HAVE_STRUCT_SIGACTION) 199 { 200 struct sigaction action; 201 sigaction(SIGHUP,NULL,&action); 202 if (action.sa_handler == SIG_IGN) { 203 ierr = PetscInfo(NULL,"SIGHUP previously set to ignore, therefor not changing its signal handler\n");CHKERRQ(ierr); 204 } else { 205 signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 206 } 207 } 208 #endif 209 #if !defined(PETSC_MISSING_SIGILL) 210 signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 211 #endif 212 #if !defined(PETSC_MISSING_SIGINT) 213 /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 214 #endif 215 #if !defined(PETSC_MISSING_SIGPIPE) 216 signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 217 #endif 218 #if !defined(PETSC_MISSING_SIGQUIT) 219 signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 220 #endif 221 #if !defined(PETSC_MISSING_SIGSEGV) 222 signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 223 #endif 224 #if !defined(PETSC_MISSING_SIGSYS) 225 signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 226 #endif 227 #if !defined(PETSC_MISSING_SIGTERM) 228 signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 229 #endif 230 #if !defined(PETSC_MISSING_SIGTRAP) 231 signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 232 #endif 233 #if !defined(PETSC_MISSING_SIGTSTP) 234 /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 235 #endif 236 #if !defined(PETSC_MISSING_SIGURG) 237 signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 238 #endif 239 #if !defined(PETSC_MISSING_SIGUSR1) 240 /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 241 #endif 242 #if !defined(PETSC_MISSING_SIGUSR2) 243 /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 244 #endif 245 SignalSet = PETSC_TRUE; 246 } 247 if (!routine) { 248 #if !defined(PETSC_MISSING_SIGALRM) 249 /* signal(SIGALRM, SIG_DFL); */ 250 #endif 251 #if !defined(PETSC_MISSING_SIGBUS) 252 signal(SIGBUS, SIG_DFL); 253 #endif 254 #if !defined(PETSC_MISSING_SIGCONT) 255 /* signal(SIGCONT, SIG_DFL); */ 256 #endif 257 #if !defined(PETSC_MISSING_SIGFPE) 258 signal(SIGFPE, SIG_DFL); 259 #endif 260 #if !defined(PETSC_MISSING_SIGHUP) 261 signal(SIGHUP, SIG_DFL); 262 #endif 263 #if !defined(PETSC_MISSING_SIGILL) 264 signal(SIGILL, SIG_DFL); 265 #endif 266 #if !defined(PETSC_MISSING_SIGINT) 267 /* signal(SIGINT, SIG_DFL); */ 268 #endif 269 #if !defined(PETSC_MISSING_SIGPIPE) 270 signal(SIGPIPE, SIG_DFL); 271 #endif 272 #if !defined(PETSC_MISSING_SIGQUIT) 273 signal(SIGQUIT, SIG_DFL); 274 #endif 275 #if !defined(PETSC_MISSING_SIGSEGV) 276 signal(SIGSEGV, SIG_DFL); 277 #endif 278 #if !defined(PETSC_MISSING_SIGSYS) 279 signal(SIGSYS, SIG_DFL); 280 #endif 281 #if !defined(PETSC_MISSING_SIGTERM) 282 signal(SIGTERM, SIG_DFL); 283 #endif 284 #if !defined(PETSC_MISSING_SIGTRAP) 285 signal(SIGTRAP, SIG_DFL); 286 #endif 287 #if !defined(PETSC_MISSING_SIGTSTP) 288 /* signal(SIGTSTP, SIG_DFL); */ 289 #endif 290 #if !defined(PETSC_MISSING_SIGURG) 291 signal(SIGURG, SIG_DFL); 292 #endif 293 #if !defined(PETSC_MISSING_SIGUSR1) 294 /* signal(SIGUSR1, SIG_DFL); */ 295 #endif 296 #if !defined(PETSC_MISSING_SIGUSR2) 297 /* signal(SIGUSR2, SIG_DFL); */ 298 #endif 299 SignalSet = PETSC_FALSE; 300 } 301 ierr = PetscNew(&newsh);CHKERRQ(ierr); 302 if (sh) { 303 if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted"); 304 newsh->previous = sh; 305 } else newsh->previous = NULL; 306 newsh->handler = routine; 307 newsh->ctx = ctx; 308 newsh->classid = SIGNAL_CLASSID; 309 sh = newsh; 310 PetscFunctionReturn(0); 311 } 312 313 /*@ 314 PetscPopSignalHandler - Removes the most last signal handler that was pushed. 315 If no signal handlers are left on the stack it will remove the PETSc signal handler. 316 (That is PETSc will no longer catch signals). 317 318 Not Collective 319 320 Level: developer 321 322 .seealso: PetscPushSignalHandler() 323 324 @*/ 325 PetscErrorCode PetscPopSignalHandler(void) 326 { 327 struct SH *tmp; 328 PetscErrorCode ierr; 329 330 PetscFunctionBegin; 331 if (!sh) PetscFunctionReturn(0); 332 if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted"); 333 334 tmp = sh; 335 sh = sh->previous; 336 ierr = PetscFree(tmp);CHKERRQ(ierr); 337 if (!sh || !sh->handler) { 338 #if !defined(PETSC_MISSING_SIGALRM) 339 /* signal(SIGALRM, SIG_DFL); */ 340 #endif 341 #if !defined(PETSC_MISSING_SIGBUS) 342 signal(SIGBUS, SIG_DFL); 343 #endif 344 #if !defined(PETSC_MISSING_SIGCONT) 345 /* signal(SIGCONT, SIG_DFL); */ 346 #endif 347 #if !defined(PETSC_MISSING_SIGFPE) 348 signal(SIGFPE, SIG_DFL); 349 #endif 350 #if !defined(PETSC_MISSING_SIGHUP) 351 signal(SIGHUP, SIG_DFL); 352 #endif 353 #if !defined(PETSC_MISSING_SIGILL) 354 signal(SIGILL, SIG_DFL); 355 #endif 356 #if !defined(PETSC_MISSING_SIGINT) 357 /* signal(SIGINT, SIG_DFL); */ 358 #endif 359 #if !defined(PETSC_MISSING_SIGPIPE) 360 signal(SIGPIPE, SIG_DFL); 361 #endif 362 #if !defined(PETSC_MISSING_SIGQUIT) 363 signal(SIGQUIT, SIG_DFL); 364 #endif 365 #if !defined(PETSC_MISSING_SIGSEGV) 366 signal(SIGSEGV, SIG_DFL); 367 #endif 368 #if !defined(PETSC_MISSING_SIGSYS) 369 signal(SIGSYS, SIG_DFL); 370 #endif 371 #if !defined(PETSC_MISSING_SIGTERM) 372 signal(SIGTERM, SIG_DFL); 373 #endif 374 #if !defined(PETSC_MISSING_SIGTRAP) 375 signal(SIGTRAP, SIG_DFL); 376 #endif 377 #if !defined(PETSC_MISSING_SIGTSTP) 378 /* signal(SIGTSTP, SIG_DFL); */ 379 #endif 380 #if !defined(PETSC_MISSING_SIGURG) 381 signal(SIGURG, SIG_DFL); 382 #endif 383 #if !defined(PETSC_MISSING_SIGUSR1) 384 /* signal(SIGUSR1, SIG_DFL); */ 385 #endif 386 #if !defined(PETSC_MISSING_SIGUSR2) 387 /* signal(SIGUSR2, SIG_DFL); */ 388 #endif 389 SignalSet = PETSC_FALSE; 390 } else { 391 SignalSet = PETSC_TRUE; 392 } 393 PetscFunctionReturn(0); 394 } 395