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