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