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