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