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 /*@ 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 /*@ 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 /*@ 86 PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal 87 88 Not Collective, No Fortran Support 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 /*@ 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] - Set debugger debug_terminal xterm or Terminal (for Apple) 195 . -display name - XDisplay to open xterm in 196 . -debugger_ranks m,n - Which MPI ranks on which to start the debugger, defaults to all 197 . -stop_for_debugger - Print a message on how to attach the process with a debugger and then wait for the user to attach 198 - -debugger_pause <secs> - Wait <secs> before attaching the debugger. This is useful for slow connections 199 that take a long time for the Terminal window or xterm to start up. 200 201 Level: advanced 202 203 Note: 204 If you get the message "`stdin` is not a `tty`, hence unable to attach debugger, see `PetscAttachDebugger()`", this means the application 205 is likely running in a batch system and you do not have terminal access to the process. You can try 206 running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger` 207 208 Developer Note: 209 Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`? 210 211 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()` 212 @*/ 213 PetscErrorCode PetscAttachDebugger(void) 214 { 215 PetscErrorCode PETSC_UNUSED ierr; 216 #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK) 217 int child = 0; 218 PetscReal sleeptime = 0; 219 char program[PETSC_MAX_PATH_LEN], display[256], hostname[64]; 220 #endif 221 222 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 223 ierr = (*PetscErrorPrintf)("System cannot start debugger\n"); 224 ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 225 ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 226 PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS); 227 #else 228 if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) { 229 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n"); 230 return PETSC_ERR_SYS; 231 } 232 if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) { 233 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 234 return PETSC_ERR_SYS; 235 } 236 if (PetscUnlikely(!program[0])) { 237 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 238 return PETSC_ERR_SYS; 239 } 240 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"); 241 child = fork(); 242 if (PetscUnlikely(child < 0)) { 243 ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n"); 244 return PETSC_ERR_SYS; 245 } 246 petscindebugger = PETSC_TRUE; 247 248 /* 249 Swap role the parent and child. This is (I think) so that control c typed 250 in the debugger goes to the correct process. 251 */ 252 #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER) 253 child = child ? 0 : getppid(); 254 #endif 255 256 if (child) { /* I am the parent, will run the debugger */ 257 const char *args[10]; 258 char pid[10]; 259 PetscInt j, jj; 260 PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb; 261 262 PetscCall(PetscGetHostName(hostname, sizeof(hostname))); 263 /* 264 We need to send a continue signal to the "child" process on the 265 alpha, otherwise it just stays off forever 266 */ 267 #if defined(PETSC_NEED_KILL_FOR_DEBUGGER) 268 kill(child, SIGCONT); 269 #endif 270 PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child)); 271 272 PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb)); 273 PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd)); 274 PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg)); 275 PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups)); 276 PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb)); 277 PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb)); 278 PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx)); 279 PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb)); 280 PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop)); 281 PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb)); 282 283 if (isxxgdb || isups || isddd) { 284 args[1] = program; 285 args[2] = pid; 286 args[3] = "-display"; 287 args[0] = PetscDebugger; 288 args[4] = display; 289 args[5] = NULL; 290 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 291 if (execvp(args[0], (char **)args) < 0) { 292 perror("Unable to start debugger"); 293 exit(0); 294 } 295 } else if (iskdbg) { 296 args[1] = "-p"; 297 args[2] = pid; 298 args[3] = program; 299 args[4] = "-display"; 300 args[0] = PetscDebugger; 301 args[5] = display; 302 args[6] = NULL; 303 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname); 304 if (execvp(args[0], (char **)args) < 0) { 305 perror("Unable to start debugger"); 306 exit(0); 307 } 308 } else if (isxldb) { 309 args[1] = "-a"; 310 args[2] = pid; 311 args[3] = program; 312 args[4] = "-display"; 313 args[0] = PetscDebugger; 314 args[5] = display; 315 args[6] = NULL; 316 printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 317 if (execvp(args[0], (char **)args) < 0) { 318 perror("Unable to start debugger"); 319 exit(0); 320 } 321 } else if (isworkshop) { 322 args[1] = "-s"; 323 args[2] = pid; 324 args[3] = "-D"; 325 args[4] = "-"; 326 args[0] = PetscDebugger; 327 args[5] = pid; 328 args[6] = "-display"; 329 args[7] = display; 330 args[8] = NULL; 331 printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname); 332 if (execvp(args[0], (char **)args) < 0) { 333 perror("Unable to start debugger"); 334 exit(0); 335 } 336 } else { 337 j = 0; 338 if (UseDebugTerminal) { 339 PetscBool cmp; 340 char *tmp, *tmp1 = NULL; 341 PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp)); 342 if (cmp) { 343 char command[1024]; 344 if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid)); 345 else { 346 char fullprogram[PETSC_MAX_PATH_LEN]; 347 PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram))); 348 PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid)); 349 } 350 #if defined(PETSC_HAVE_POPEN) 351 PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL)); 352 #else 353 printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n"); 354 #endif 355 exit(0); 356 } 357 358 PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp)); 359 if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp)); 360 if (cmp) display[0] = 0; /* when using screen, we never pass -display */ 361 args[j++] = tmp = DebugTerminal; 362 if (display[0]) { 363 args[j++] = "-display"; 364 args[j++] = display; 365 } 366 while (*tmp) { 367 PetscCall(PetscStrchr(tmp, ' ', &tmp1)); 368 if (!tmp1) break; 369 *tmp1 = 0; 370 tmp = tmp1 + 1; 371 args[j++] = tmp; 372 } 373 } 374 args[j++] = PetscDebugger; 375 jj = j; 376 /* this is for default gdb */ 377 args[j++] = program; 378 args[j++] = pid; 379 args[j++] = NULL; 380 381 if (isidb) { 382 j = jj; 383 args[j++] = "-pid"; 384 args[j++] = pid; 385 args[j++] = "-gdb"; 386 args[j++] = program; 387 args[j++] = NULL; 388 } 389 if (islldb) { 390 j = jj; 391 args[j++] = "-p"; 392 args[j++] = pid; 393 args[j++] = NULL; 394 } 395 if (isdbx) { 396 j = jj; 397 #if defined(PETSC_USE_P_FOR_DEBUGGER) 398 args[j++] = "-p"; 399 args[j++] = pid; 400 args[j++] = program; 401 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 402 args[j++] = "-l"; 403 args[j++] = "ALL"; 404 args[j++] = "-P"; 405 args[j++] = pid; 406 args[j++] = program; 407 #elif defined(PETSC_USE_A_FOR_DEBUGGER) 408 args[j++] = "-a"; 409 args[j++] = pid; 410 #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 411 args[j++] = "-pid"; 412 args[j++] = pid; 413 args[j++] = program; 414 #else 415 args[j++] = program; 416 args[j++] = pid; 417 #endif 418 args[j++] = NULL; 419 } 420 if (UseDebugTerminal) { 421 if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname); 422 else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname); 423 424 if (execvp(args[0], (char **)args) < 0) { 425 perror("Unable to start debugger in xterm"); 426 exit(0); 427 } 428 } else { 429 printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname); 430 if (execvp(args[0], (char **)args) < 0) { 431 perror("Unable to start debugger"); 432 exit(0); 433 } 434 } 435 } 436 } else { /* I am the child, continue with user code */ 437 sleeptime = 10; /* default to sleep waiting for debugger */ 438 PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); 439 if (sleeptime < 0) sleeptime = -sleeptime; 440 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 441 /* 442 HP cannot attach process to sleeping debugger, hence count instead 443 */ 444 { 445 PetscReal x = 1.0; 446 int i = 10000000; 447 while (i--) x++; /* cannot attach to sleeper */ 448 } 449 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 450 /* 451 IBM sleep may return at anytime, hence must see if there is more time to sleep 452 */ 453 { 454 int left = sleeptime; 455 while (left > 0) left = PetscSleep(left) - 1; 456 } 457 #else 458 PetscCall(PetscSleep(sleeptime)); 459 #endif 460 } 461 #endif 462 return PETSC_SUCCESS; 463 } 464 465 /*@C 466 PetscAttachDebuggerErrorHandler - Error handler that attaches 467 a debugger to a running process when an error is detected. 468 This routine is useful for examining variables, etc. 469 470 Not Collective, No Fortran Support 471 472 Input Parameters: 473 + comm - communicator over which error occurred 474 . line - the line number of the error (usually indicated by `__LINE__` in the calling routine) 475 . fun - the function name of the calling routine 476 . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine) 477 . mess - an error text string, usually just printed to the screen 478 . num - the generic error number 479 . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT` 480 - ctx - error handler context 481 482 Level: developer 483 484 Notes: 485 By default the GNU debugger, gdb, is used except on macOS where lldb is used. Alternatives are cuda-gdb, lldb, dbx and 486 xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 487 488 Most users need not directly employ this routine and the other error 489 handlers, but can instead use the simplified interface SETERR, which has 490 the calling sequence 491 .vb 492 SETERRQ(PETSC_COMM_SELF, number, p, message) 493 .ve 494 495 Use `PetscPushErrorHandler()` to set the desired error handler. The 496 currently available PETSc error handlers are 497 .vb 498 PetscTraceBackErrorHandler() 499 PetscAttachDebuggerErrorHandler() 500 PetscAbortErrorHandler() 501 .ve 502 or you may write your own. 503 504 Developer Note: 505 This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception 506 causing the debugger to be attached again in a cycle. 507 508 .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, 509 `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()` 510 @*/ 511 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx) 512 { 513 (void)comm; 514 (void)num; 515 (void)p; 516 (void)ctx; 517 if (!mess) mess = " "; 518 519 if (fun) (void)(*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess); 520 else (void)(*PetscErrorPrintf)("%s:%d %s\n", file, line, mess); 521 522 (void)PetscAttachDebugger(); 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 /*@ 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, No Fortran Support 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