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