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