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