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