1 /* 2 Code to handle PETSc starting up in debuggers,etc. 3 */ 4 #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fileno() */ 5 #include <petscsys.h> /*I "petscsys.h" I*/ 6 #include <signal.h> 7 #if defined(PETSC_HAVE_UNISTD_H) 8 #include <unistd.h> 9 #endif 10 11 /* 12 These are the debugger and display used if the debugger is started up 13 */ 14 static char PetscDebugger[PETSC_MAX_PATH_LEN]; 15 static char DebugTerminal[PETSC_MAX_PATH_LEN]; 16 static PetscBool UseDebugTerminal = PETSC_TRUE; 17 PetscBool petscwaitonerrorflg = PETSC_FALSE; 18 PetscBool petscindebugger = PETSC_FALSE; 19 20 /*@C 21 PetscSetDebugTerminal - Sets the terminal to use for debugging. 22 23 Not Collective; No Fortran Support 24 25 Input Parameter: 26 . terminal - name of terminal and any flags required to execute a program. 27 For example "xterm", "urxvt -e", "gnome-terminal -x". 28 On Apple macOS you can use "Terminal} (note the capital T) 29 30 Options Database Key: 31 . -debug_terminal terminal - use this terminal instead of the default 32 33 Level: developer 34 35 Notes: 36 You can start the debugger for all processes in the same GNU screen session. 37 38 $ mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen" 39 40 will open 4 windows in the session named "debug". 41 42 The default on Apple is Terminal, on other systems the default is xterm 43 44 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()` 45 @*/ 46 PetscErrorCode PetscSetDebugTerminal(const char terminal[]) 47 { 48 PetscBool xterm; 49 50 PetscFunctionBegin; 51 PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal))); 52 PetscCall(PetscStrcmp(terminal, "xterm", &xterm)); 53 if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal))); 54 PetscFunctionReturn(PETSC_SUCCESS); 55 } 56 57 /*@C 58 PetscSetDebugger - Sets options associated with the debugger. 59 60 Not Collective; No Fortran Support 61 62 Input Parameters: 63 + debugger - name of debugger, which should be in your path, 64 usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX 65 supports "xdb", and IBM rs6000 supports "xldb". 66 67 - usedebugterminal - flag to indicate debugger window, set to either PETSC_TRUE (to indicate 68 debugger should be started in a new terminal window) or PETSC_FALSE (to start debugger 69 in initial window (the option PETSC_FALSE makes no sense when using more 70 than one MPI process.) 71 72 Level: developer 73 74 .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()` 75 @*/ 76 PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal) 77 { 78 PetscFunctionBegin; 79 if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger))); 80 if (UseDebugTerminal) UseDebugTerminal = usedebugterminal; 81 PetscFunctionReturn(PETSC_SUCCESS); 82 } 83 84 /*@C 85 PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal 86 87 Not Collective 88 89 Level: developer 90 91 .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()` 92 @*/ 93 PetscErrorCode PetscSetDefaultDebugger(void) 94 { 95 PetscFunctionBegin; 96 #if defined(PETSC_USE_DEBUGGER) 97 PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE)); 98 #endif 99 #if defined(__APPLE__) 100 PetscCall(PetscSetDebugTerminal("Terminal")); 101 #else 102 PetscCall(PetscSetDebugTerminal("xterm")); 103 #endif 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[]) 108 { 109 char *f = NULL; 110 111 PetscFunctionBegin; 112 PetscCall(PetscStrstr(string, defaultDbg, &f)); 113 if (f) { 114 PetscBool exists; 115 116 PetscCall(PetscTestFile(string, 'x', &exists)); 117 if (exists) *debugger = string; 118 else *debugger = defaultDbg; 119 } 120 PetscFunctionReturn(PETSC_SUCCESS); 121 } 122 123 /*@C 124 PetscSetDebuggerFromString - Set the complete path for the 125 debugger for PETSc to use. 126 127 Not Collective 128 129 Input Parameter: 130 . string - the name of the debugger, for example "gdb" 131 132 Level: developer 133 134 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()` 135 @*/ 136 PetscErrorCode PetscSetDebuggerFromString(const char *string) 137 { 138 const char *debugger = NULL; 139 PetscBool useterminal = PETSC_TRUE; 140 char *f = NULL; 141 142 PetscFunctionBegin; 143 PetscCall(PetscStrstr(string, "noxterm", &f)); 144 if (f) useterminal = PETSC_FALSE; 145 PetscCall(PetscStrstr(string, "ddd", &f)); 146 if (f) useterminal = PETSC_FALSE; 147 PetscCall(PetscStrstr(string, "noterminal", &f)); 148 if (f) useterminal = PETSC_FALSE; 149 PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger)); 150 PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger)); 151 PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger)); 152 PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger)); 153 PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger)); 154 PetscCall(PetscCheckDebugger_Private("idb", string, &debugger)); 155 PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger)); 156 PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger)); 157 PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger)); 158 PetscCall(PetscCheckDebugger_Private("ups", string, &debugger)); 159 PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger)); 160 PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger)); 161 PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger)); 162 PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger)); 163 PetscCall(PetscSetDebugger(debugger, useterminal)); 164 PetscFunctionReturn(PETSC_SUCCESS); 165 } 166 167 /*@ 168 PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead 169 of exiting. 170 171 Not Collective 172 173 Level: advanced 174 175 Note: 176 When `-start_in_debugger -debugger_ranks x,y,z` is used this prevents the processes NOT listed in x,y,z from calling `MPI_Abort()` and 177 killing the user's debugging sessions. 178 179 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()` 180 @*/ 181 PetscErrorCode PetscWaitOnError(void) 182 { 183 petscwaitonerrorflg = PETSC_TRUE; 184 return PETSC_SUCCESS; 185 } 186 187 /*@ 188 PetscAttachDebugger - Attaches the debugger to the running process. 189 190 Not Collective 191 192 Options Database Keys: 193 + -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] - set debugger debug_terminal xterm or Terminal (for Apple) 194 . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment 195 - -stop_for_debugger - print a message on how to attach the process with a debugger and then wait for the user to attach 196 197 Level: advanced 198 199 Note: 200 If you get the message " stdin is not a tty, hence unable to attach debugger, see PetscAttachDebugger()", this means the application 201 is likely running in a batch system and you do not have terminal access to the process. You can try 202 running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger` 203 204 Developer Notes: 205 Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`? 206 207 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()` 208 @*/ 209 PetscErrorCode PetscAttachDebugger(void) 210 { 211 PetscErrorCode PETSC_UNUSED ierr; 212 #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK) 213 int child = 0; 214 PetscReal sleeptime = 0; 215 char program[PETSC_MAX_PATH_LEN], display[256], hostname[64]; 216 #endif 217 218 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 219 ierr = (*PetscErrorPrintf)("System cannot start debugger\n"); 220 ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 221 ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 222 PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS); 223 #else 224 if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) { 225 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n"); 226 return PETSC_ERR_SYS; 227 } 228 if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) { 229 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 230 return PETSC_ERR_SYS; 231 } 232 if (PetscUnlikely(!program[0])) { 233 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 234 return PETSC_ERR_SYS; 235 } 236 if (PetscUnlikely(!isatty(fileno(stdin))) && !UseDebugTerminal) { printf("If the debugger exits immediately or hangs, this indicates you cannot use PetscAttachDebugger() in this situation\n\n"); } 237 child = (int)fork(); 238 if (PetscUnlikely(child < 0)) { 239 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n"); 240 return PETSC_ERR_SYS; 241 } 242 petscindebugger = PETSC_TRUE; 243 244 /* 245 Swap role the parent and child. This is (I think) so that control c typed 246 in the debugger goes to the correct process. 247 */ 248 #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER) 249 child = child ? 0 : (int)getppid(); 250 #endif 251 252 if (child) { /* I am the parent, will run the debugger */ 253 const char *args[10]; 254 char pid[10]; 255 PetscInt j, jj; 256 PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb; 257 258 PetscCall(PetscGetHostName(hostname, sizeof(hostname))); 259 /* 260 We need to send a continue signal to the "child" process on the 261 alpha, otherwise it just stays off forever 262 */ 263 #if defined(PETSC_NEED_KILL_FOR_DEBUGGER) 264 kill(child, SIGCONT); 265 #endif 266 PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child)); 267 268 PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb)); 269 PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd)); 270 PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg)); 271 PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups)); 272 PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb)); 273 PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb)); 274 PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx)); 275 PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb)); 276 PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop)); 277 PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb)); 278 279 if (isxxgdb || isups || isddd) { 280 args[1] = program; 281 args[2] = pid; 282 args[3] = "-display"; 283 args[0] = PetscDebugger; 284 args[4] = display; 285 args[5] = NULL; 286 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 287 if (execvp(args[0], (char **)args) < 0) { 288 perror("Unable to start debugger"); 289 exit(0); 290 } 291 } else if (iskdbg) { 292 args[1] = "-p"; 293 args[2] = pid; 294 args[3] = program; 295 args[4] = "-display"; 296 args[0] = PetscDebugger; 297 args[5] = display; 298 args[6] = NULL; 299 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname); 300 if (execvp(args[0], (char **)args) < 0) { 301 perror("Unable to start debugger"); 302 exit(0); 303 } 304 } else if (isxldb) { 305 args[1] = "-a"; 306 args[2] = pid; 307 args[3] = program; 308 args[4] = "-display"; 309 args[0] = PetscDebugger; 310 args[5] = display; 311 args[6] = NULL; 312 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 313 if (execvp(args[0], (char **)args) < 0) { 314 perror("Unable to start debugger"); 315 exit(0); 316 } 317 } else if (isworkshop) { 318 args[1] = "-s"; 319 args[2] = pid; 320 args[3] = "-D"; 321 args[4] = "-"; 322 args[0] = PetscDebugger; 323 args[5] = pid; 324 args[6] = "-display"; 325 args[7] = display; 326 args[8] = NULL; 327 printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname); 328 if (execvp(args[0], (char **)args) < 0) { 329 perror("Unable to start debugger"); 330 exit(0); 331 } 332 } else { 333 j = 0; 334 if (UseDebugTerminal) { 335 PetscBool cmp; 336 char *tmp, *tmp1 = NULL; 337 PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp)); 338 if (cmp) { 339 char command[1024]; 340 if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid)); 341 else { 342 char fullprogram[PETSC_MAX_PATH_LEN]; 343 PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram))); 344 PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid)); 345 } 346 #if defined(PETSC_HAVE_POPEN) 347 PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL)); 348 #else 349 printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n"); 350 #endif 351 exit(0); 352 } 353 354 PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp)); 355 if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp)); 356 if (cmp) display[0] = 0; /* when using screen, we never pass -display */ 357 args[j++] = tmp = DebugTerminal; 358 if (display[0]) { 359 args[j++] = "-display"; 360 args[j++] = display; 361 } 362 while (*tmp) { 363 PetscCall(PetscStrchr(tmp, ' ', &tmp1)); 364 if (!tmp1) break; 365 *tmp1 = 0; 366 tmp = tmp1 + 1; 367 args[j++] = tmp; 368 } 369 } 370 args[j++] = PetscDebugger; 371 jj = j; 372 /* this is for default gdb */ 373 args[j++] = program; 374 args[j++] = pid; 375 args[j++] = NULL; 376 377 if (isidb) { 378 j = jj; 379 args[j++] = "-pid"; 380 args[j++] = pid; 381 args[j++] = "-gdb"; 382 args[j++] = program; 383 args[j++] = NULL; 384 } 385 if (islldb) { 386 j = jj; 387 args[j++] = "-p"; 388 args[j++] = pid; 389 args[j++] = NULL; 390 } 391 if (isdbx) { 392 j = jj; 393 #if defined(PETSC_USE_P_FOR_DEBUGGER) 394 args[j++] = "-p"; 395 args[j++] = pid; 396 args[j++] = program; 397 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 398 args[j++] = "-l"; 399 args[j++] = "ALL"; 400 args[j++] = "-P"; 401 args[j++] = pid; 402 args[j++] = program; 403 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 404 args[j++] = "-a"; 405 args[j++] = pid; 406 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 407 args[j++] = "-pid"; 408 args[j++] = pid; 409 args[j++] = program; 410 #else 411 args[j++] = program; 412 args[j++] = pid; 413 #endif 414 args[j++] = NULL; 415 } 416 if (UseDebugTerminal) { 417 if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname); 418 else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname); 419 420 if (execvp(args[0], (char **)args) < 0) { 421 perror("Unable to start debugger in xterm"); 422 exit(0); 423 } 424 } else { 425 printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname); 426 if (execvp(args[0], (char **)args) < 0) { 427 perror("Unable to start debugger"); 428 exit(0); 429 } 430 } 431 } 432 } else { /* I am the child, continue with user code */ 433 sleeptime = 10; /* default to sleep waiting for debugger */ 434 PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); 435 if (sleeptime < 0) sleeptime = -sleeptime; 436 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 437 /* 438 HP cannot attach process to sleeping debugger, hence count instead 439 */ 440 { 441 PetscReal x = 1.0; 442 int i = 10000000; 443 while (i--) x++; /* cannot attach to sleeper */ 444 } 445 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 446 /* 447 IBM sleep may return at anytime, hence must see if there is more time to sleep 448 */ 449 { 450 int left = sleeptime; 451 while (left > 0) left = PetscSleep(left) - 1; 452 } 453 #else 454 PetscCall(PetscSleep(sleeptime)); 455 #endif 456 } 457 #endif 458 return PETSC_SUCCESS; 459 } 460 461 /*@C 462 PetscAttachDebuggerErrorHandler - Error handler that attaches 463 a debugger to a running process when an error is detected. 464 This routine is useful for examining variables, etc. 465 466 Not Collective 467 468 Input Parameters: 469 + comm - communicator over which error occurred 470 . line - the line number of the error (indicated by `__LINE__`) 471 . fun - the function name 472 . file - the file in which the error was detected (indicated by `__FILE__`) 473 . mess - an error text string, usually just printed to the screen 474 . num - the generic error number 475 . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT` 476 - ctx - error handler context 477 478 Level: developer 479 480 Notes: 481 By default the Gnu debugger, gdb, is used. Alternatives are cuda-gdb, lldb, dbx and 482 xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 483 484 Most users need not directly employ this routine and the other error 485 handlers, but can instead use the simplified interface SETERR, which has 486 the calling sequence 487 $ SETERRQ(PETSC_COMM_SELF, number, p, message) 488 489 Notes for experienced users: 490 Use `PetscPushErrorHandler()` to set the desired error handler. The 491 currently available PETSc error handlers are 492 .vb 493 PetscTraceBackErrorHandler() 494 PetscAttachDebuggerErrorHandler() 495 PetscAbortErrorHandler() 496 .ve 497 or you may write your own. 498 499 Developer Notes: 500 This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception 501 causing the debugger to be attached again in a cycle. 502 503 .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, 504 `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()` 505 @*/ 506 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx) 507 { 508 PetscErrorCode ierr; 509 510 (void)comm; 511 (void)num; 512 (void)p; 513 (void)ctx; 514 if (!mess) mess = " "; 515 516 if (fun) ierr = (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess); 517 else ierr = (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess); 518 519 ierr = PetscAttachDebugger(); 520 (void)ierr; 521 abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */ 522 PetscFunctionReturn(PETSC_SUCCESS); 523 } 524 525 /*@C 526 PetscStopForDebugger - Prints a message to the screen indicating how to 527 attach to the process with the debugger and then waits for the 528 debugger to attach. 529 530 Not Collective 531 532 Options Database Key: 533 . -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called 534 535 Level: developer 536 537 Note: 538 This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work. 539 540 Developer Notes: 541 Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`? 542 543 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()` 544 @*/ 545 PetscErrorCode PetscStopForDebugger(void) 546 { 547 PetscErrorCode ierr; 548 PetscInt sleeptime = 0; 549 #if !defined(PETSC_CANNOT_START_DEBUGGER) 550 int ppid; 551 PetscMPIInt rank; 552 char program[PETSC_MAX_PATH_LEN], hostname[256]; 553 PetscBool isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb; 554 #endif 555 556 PetscFunctionBegin; 557 #if defined(PETSC_CANNOT_START_DEBUGGER) 558 PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n")); 559 #else 560 if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */ 561 ierr = PetscGetHostName(hostname, sizeof(hostname)); 562 if (ierr) { 563 PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n")); 564 PetscFunctionReturn(PETSC_SUCCESS); 565 } 566 567 ierr = PetscGetProgramName(program, sizeof(program)); 568 if (ierr) { 569 PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n")); 570 PetscFunctionReturn(PETSC_SUCCESS); 571 } 572 if (!program[0]) { 573 PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n")); 574 PetscFunctionReturn(PETSC_SUCCESS); 575 } 576 577 ppid = getpid(); 578 579 PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb)); 580 PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd)); 581 PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg)); 582 PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups)); 583 PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb)); 584 PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb)); 585 PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx)); 586 PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb)); 587 588 if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid); 589 else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program); 590 else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid); 591 else if (isdbx) { 592 #if defined(PETSC_USE_P_FOR_DEBUGGER) 593 printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program); 594 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 595 printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program); 596 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 597 printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid); 598 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 599 printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program); 600 #else 601 printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid); 602 #endif 603 } 604 #endif /* PETSC_CANNOT_START_DEBUGGER */ 605 606 fflush(stdout); /* ignore error because may already be in error handler */ 607 608 sleeptime = 25; /* default to sleep waiting for debugger */ 609 PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */ 610 if (sleeptime < 0) sleeptime = -sleeptime; 611 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 612 /* 613 HP cannot attach process to sleeping debugger, hence count instead 614 */ 615 { 616 // this *will* get optimized away by any compiler known to man 617 PetscReal x = 1.0; 618 int i = 10000000; 619 while (i--) x++; /* cannot attach to sleeper */ 620 } 621 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 622 /* 623 IBM sleep may return at anytime, hence must see if there is more time to sleep 624 */ 625 { 626 int left = sleeptime; 627 while (left > 0) left = sleep(left) - 1; 628 } 629 #else 630 PetscCall(PetscSleep(sleeptime)); 631 #endif 632 PetscFunctionReturn(PETSC_SUCCESS); 633 } 634