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