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