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 #undef __FUNCT__ 21 #define __FUNCT__ "PetscSignalHandler_Private" 22 /* 23 PetscSignalHandler_Private - This is the signal handler called by the system. This calls 24 any signal handler set by PETSc or the application code. 25 26 Input Parameters: (depends on system) 27 . sig - integer code indicating the type of signal 28 . code - ?? 29 . sigcontext - ?? 30 . addr - ?? 31 32 Note: this is declared extern "C" because it is passed to the system routine signal() 33 which is an extern "C" routine. The Solaris 2.7 OS compilers require that this be 34 extern "C". 35 36 */ 37 #if defined(PETSC_HAVE_4ARG_SIGNAL_HANDLER) 38 static void PetscSignalHandler_Private(int sig,int code,struct sigcontext * scp,char *addr) 39 #else 40 static void PetscSignalHandler_Private(int sig) 41 #endif 42 { 43 PetscErrorCode ierr; 44 45 PetscFunctionBegin; 46 if (!sh || !sh->handler) ierr = PetscSignalHandlerDefault(sig,(void*)0); 47 else { 48 if (sh->classid != SIGNAL_CLASSID) SETERRABORT(PETSC_COMM_WORLD,PETSC_ERR_COR,"Signal object has been corrupted"); 49 ierr = (*sh->handler)(sig,sh->ctx); 50 } 51 if (ierr) MPI_Abort(PETSC_COMM_WORLD,0); 52 } 53 54 #undef __FUNCT__ 55 #define __FUNCT__ "PetscSignalHandlerDefault" 56 /*@ 57 PetscSignalHandlerDefault - Default signal handler. 58 59 Not Collective 60 61 Level: advanced 62 63 Input Parameters: 64 + sig - signal value 65 - ptr - unused pointer 66 67 Concepts: signal handler^default 68 69 @*/ 70 PetscErrorCode PetscSignalHandlerDefault(int sig,void *ptr) 71 { 72 PetscErrorCode ierr; 73 const char *SIGNAME[64]; 74 75 PetscFunctionBegin; 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: Somet 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 http://www.mcs.anl.gov/petsc/documentation/faq.html#valgrind"); 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","unknown directory",PETSC_ERR_SIG,PETSC_ERROR_INITIAL,NULL); 161 MPI_Abort(PETSC_COMM_WORLD,(int)ierr); 162 PetscFunctionReturn(0); 163 } 164 165 #if !defined(PETSC_SIGNAL_CAST) 166 #define PETSC_SIGNAL_CAST 167 #endif 168 169 #undef __FUNCT__ 170 #define __FUNCT__ "PetscPushSignalHandler" 171 /*@C 172 PetscPushSignalHandler - Catches the usual fatal errors and 173 calls a user-provided routine. 174 175 Not Collective 176 177 Input Parameter: 178 + routine - routine to call when a signal is received 179 - ctx - optional context needed by the routine 180 181 Level: developer 182 183 Concepts: signal handler^setting 184 185 .seealso: PetscPopSignalHandler(), PetscSignalHandlerDefault(), PetscPushErrorHandler() 186 187 @*/ 188 PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*routine)(int,void*),void *ctx) 189 { 190 struct SH *newsh; 191 PetscErrorCode ierr; 192 193 PetscFunctionBegin; 194 if (!SIGNAL_CLASSID) { 195 /* ierr = PetscClassIdRegister("Signal",&SIGNAL_CLASSID);CHKERRQ(ierr); */ 196 SIGNAL_CLASSID = 19; 197 } 198 if (!SignalSet && routine) { 199 /* Do not catch ABRT, CHLD, KILL */ 200 #if !defined(PETSC_MISSING_SIGALRM) 201 /* signal(SIGALRM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 202 #endif 203 #if !defined(PETSC_MISSING_SIGBUS) 204 signal(SIGBUS, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 205 #endif 206 #if !defined(PETSC_MISSING_SIGCONT) 207 /*signal(SIGCONT, PETSC_SIGNAL_CAST PetscSignalHandler_Private);*/ 208 #endif 209 #if !defined(PETSC_MISSING_SIGFPE) 210 signal(SIGFPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 211 #endif 212 #if !defined(PETSC_MISSING_SIGHUP) 213 signal(SIGHUP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 214 #endif 215 #if !defined(PETSC_MISSING_SIGILL) 216 signal(SIGILL, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 217 #endif 218 #if !defined(PETSC_MISSING_SIGINT) 219 /* signal(SIGINT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 220 #endif 221 #if !defined(PETSC_MISSING_SIGPIPE) 222 signal(SIGPIPE, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 223 #endif 224 #if !defined(PETSC_MISSING_SIGQUIT) 225 signal(SIGQUIT, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 226 #endif 227 #if !defined(PETSC_MISSING_SIGSEGV) 228 signal(SIGSEGV, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 229 #endif 230 #if !defined(PETSC_MISSING_SIGSYS) 231 signal(SIGSYS, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 232 #endif 233 #if !defined(PETSC_MISSING_SIGTERM) 234 signal(SIGTERM, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 235 #endif 236 #if !defined(PETSC_MISSING_SIGTRAP) 237 signal(SIGTRAP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 238 #endif 239 #if !defined(PETSC_MISSING_SIGTSTP) 240 /* signal(SIGTSTP, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 241 #endif 242 #if !defined(PETSC_MISSING_SIGURG) 243 signal(SIGURG, PETSC_SIGNAL_CAST PetscSignalHandler_Private); 244 #endif 245 #if !defined(PETSC_MISSING_SIGUSR1) 246 /* signal(SIGUSR1, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 247 #endif 248 #if !defined(PETSC_MISSING_SIGUSR2) 249 /* signal(SIGUSR2, PETSC_SIGNAL_CAST PetscSignalHandler_Private); */ 250 #endif 251 SignalSet = PETSC_TRUE; 252 } 253 if (!routine) { 254 #if !defined(PETSC_MISSING_SIGALRM) 255 /* signal(SIGALRM, 0); */ 256 #endif 257 #if !defined(PETSC_MISSING_SIGBUS) 258 signal(SIGBUS, 0); 259 #endif 260 #if !defined(PETSC_MISSING_SIGCONT) 261 /* signal(SIGCONT, 0); */ 262 #endif 263 #if !defined(PETSC_MISSING_SIGFPE) 264 signal(SIGFPE, 0); 265 #endif 266 #if !defined(PETSC_MISSING_SIGHUP) 267 signal(SIGHUP, 0); 268 #endif 269 #if !defined(PETSC_MISSING_SIGILL) 270 signal(SIGILL, 0); 271 #endif 272 #if !defined(PETSC_MISSING_SIGINT) 273 /* signal(SIGINT, 0); */ 274 #endif 275 #if !defined(PETSC_MISSING_SIGPIPE) 276 signal(SIGPIPE, 0); 277 #endif 278 #if !defined(PETSC_MISSING_SIGQUIT) 279 signal(SIGQUIT, 0); 280 #endif 281 #if !defined(PETSC_MISSING_SIGSEGV) 282 signal(SIGSEGV, 0); 283 #endif 284 #if !defined(PETSC_MISSING_SIGSYS) 285 signal(SIGSYS, 0); 286 #endif 287 #if !defined(PETSC_MISSING_SIGTERM) 288 signal(SIGTERM, 0); 289 #endif 290 #if !defined(PETSC_MISSING_SIGTRAP) 291 signal(SIGTRAP, 0); 292 #endif 293 #if !defined(PETSC_MISSING_SIGTSTP) 294 /* signal(SIGTSTP, 0); */ 295 #endif 296 #if !defined(PETSC_MISSING_SIGURG) 297 signal(SIGURG, 0); 298 #endif 299 #if !defined(PETSC_MISSING_SIGUSR1) 300 /* signal(SIGUSR1, 0); */ 301 #endif 302 #if !defined(PETSC_MISSING_SIGUSR2) 303 /* signal(SIGUSR2, 0); */ 304 #endif 305 SignalSet = PETSC_FALSE; 306 } 307 ierr = PetscNew(struct SH,&newsh);CHKERRQ(ierr); 308 if (sh) { 309 if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted"); 310 newsh->previous = sh; 311 } else newsh->previous = 0; 312 newsh->handler = routine; 313 newsh->ctx = ctx; 314 newsh->classid = SIGNAL_CLASSID; 315 sh = newsh; 316 PetscFunctionReturn(0); 317 } 318 319 #undef __FUNCT__ 320 #define __FUNCT__ "PetscPopSignalHandler" 321 /*@ 322 PetscPopSignalHandler - Removes the most last signal handler that was pushed. 323 If no signal handlers are left on the stack it will remove the PETSc signal handler. 324 (That is PETSc will no longer catch signals). 325 326 Not Collective 327 328 Level: developer 329 330 Concepts: signal handler^setting 331 332 .seealso: PetscPushSignalHandler() 333 334 @*/ 335 PetscErrorCode PetscPopSignalHandler(void) 336 { 337 struct SH *tmp; 338 339 PetscFunctionBegin; 340 if (!sh) PetscFunctionReturn(0); 341 if (sh->classid != SIGNAL_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_COR,"Signal object has been corrupted"); 342 343 tmp = sh; 344 sh = sh->previous; 345 PetscFreeVoid(tmp); 346 if (!sh || !sh->handler) { 347 #if !defined(PETSC_MISSING_SIGALRM) 348 /* signal(SIGALRM, 0); */ 349 #endif 350 #if !defined(PETSC_MISSING_SIGBUS) 351 signal(SIGBUS, 0); 352 #endif 353 #if !defined(PETSC_MISSING_SIGCONT) 354 /* signal(SIGCONT, 0); */ 355 #endif 356 #if !defined(PETSC_MISSING_SIGFPE) 357 signal(SIGFPE, 0); 358 #endif 359 #if !defined(PETSC_MISSING_SIGHUP) 360 signal(SIGHUP, 0); 361 #endif 362 #if !defined(PETSC_MISSING_SIGILL) 363 signal(SIGILL, 0); 364 #endif 365 #if !defined(PETSC_MISSING_SIGINT) 366 /* signal(SIGINT, 0); */ 367 #endif 368 #if !defined(PETSC_MISSING_SIGPIPE) 369 signal(SIGPIPE, 0); 370 #endif 371 #if !defined(PETSC_MISSING_SIGQUIT) 372 signal(SIGQUIT, 0); 373 #endif 374 #if !defined(PETSC_MISSING_SIGSEGV) 375 signal(SIGSEGV, 0); 376 #endif 377 #if !defined(PETSC_MISSING_SIGSYS) 378 signal(SIGSYS, 0); 379 #endif 380 #if !defined(PETSC_MISSING_SIGTERM) 381 signal(SIGTERM, 0); 382 #endif 383 #if !defined(PETSC_MISSING_SIGTRAP) 384 signal(SIGTRAP, 0); 385 #endif 386 #if !defined(PETSC_MISSING_SIGTSTP) 387 /* signal(SIGTSTP, 0); */ 388 #endif 389 #if !defined(PETSC_MISSING_SIGURG) 390 signal(SIGURG, 0); 391 #endif 392 #if !defined(PETSC_MISSING_SIGUSR1) 393 /* signal(SIGUSR1, 0); */ 394 #endif 395 #if !defined(PETSC_MISSING_SIGUSR2) 396 /* signal(SIGUSR2, 0); */ 397 #endif 398 SignalSet = PETSC_FALSE; 399 } else { 400 SignalSet = PETSC_TRUE; 401 } 402 PetscFunctionReturn(0); 403 } 404 405 406 #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_SIGINFO_T) 407 #include <setjmp.h> 408 PETSC_VISIBILITY_INTERNAL jmp_buf PetscSegvJumpBuf; 409 /* 410 This routine is called if a segmentation violation, i.e. inaccessible memory access 411 is triggered when PETSc is testing for a buggy pointer with PetscCheckPointer() 412 413 It simply unrolls the UNIX signal and returns to the location where setjump(PetscSeqvJumpBuf) is declared. 414 */ 415 PETSC_INTERN void PetscSegv_sigaction(int signal, siginfo_t *si, void *arg) 416 { 417 longjmp(PetscSegvJumpBuf,1); 418 return; 419 } 420 #endif 421 422 423