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