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