Actual source code: adebug.c

      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>
      6: #include <signal.h>
      7: #if defined(PETSC_HAVE_UNISTD_H)
      8:   #include <unistd.h>
      9: #endif

     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;

     20: /*@
     21:   PetscSetDebugTerminal - Sets the terminal to use for debugging.

     23:   Not Collective; No Fortran Support

     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)

     30:   Options Database Key:
     31: . -debug_terminal terminal - use this terminal instead of the default

     33:   Level: developer

     35:   Notes:
     36:   You can start the debugger for all processes in the same GNU screen session.
     37: .vb
     38:   mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
     39: .ve

     41:   will open 4 windows in the session named "debug".

     43:   The default terminal on Apple is Terminal, on other systems the default is xterm

     45: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
     46: @*/
     47: PetscErrorCode PetscSetDebugTerminal(const char terminal[])
     48: {
     49:   PetscBool xterm;

     51:   PetscFunctionBegin;
     52:   PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal)));
     53:   PetscCall(PetscStrcmp(terminal, "xterm", &xterm));
     54:   if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal)));
     55:   PetscFunctionReturn(PETSC_SUCCESS);
     56: }

     58: /*@
     59:   PetscSetDebugger - Sets options associated with the debugger.

     61:   Not Collective; No Fortran Support

     63:   Input Parameters:
     64: + debugger         - name of debugger, which should be in your path,
     65:                      usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
     66:                      supports "xdb", and IBM rs6000 supports "xldb".

     68: - usedebugterminal - flag to indicate debugger window, set to either `PETSC_TRUE` (to indicate
     69:                      debugger should be started in a new terminal window) or `PETSC_FALSE` (to start debugger
     70:                      in initial window (the option `PETSC_FALSE` makes no sense when using more
     71:                      than one MPI process.)

     73:   Level: developer

     75: .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
     76: @*/
     77: PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
     78: {
     79:   PetscFunctionBegin;
     80:   if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger)));
     81:   if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
     82:   PetscFunctionReturn(PETSC_SUCCESS);
     83: }

     85: /*@
     86:   PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal

     88:   Not Collective, No Fortran Support

     90:   Level: developer

     92: .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()`
     93: @*/
     94: PetscErrorCode PetscSetDefaultDebugger(void)
     95: {
     96:   PetscFunctionBegin;
     97: #if defined(PETSC_USE_DEBUGGER)
     98:   PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE));
     99: #endif
    100: #if defined(__APPLE__)
    101:   PetscCall(PetscSetDebugTerminal("Terminal"));
    102: #else
    103:   PetscCall(PetscSetDebugTerminal("xterm"));
    104: #endif
    105:   PetscFunctionReturn(PETSC_SUCCESS);
    106: }

    108: static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
    109: {
    110:   char *f = NULL;

    112:   PetscFunctionBegin;
    113:   PetscCall(PetscStrstr(string, defaultDbg, &f));
    114:   if (f) {
    115:     PetscBool exists;

    117:     PetscCall(PetscTestFile(string, 'x', &exists));
    118:     if (exists) *debugger = string;
    119:     else *debugger = defaultDbg;
    120:   }
    121:   PetscFunctionReturn(PETSC_SUCCESS);
    122: }

    124: /*@
    125:   PetscSetDebuggerFromString - Set the complete path for the
    126:   debugger for PETSc to use.

    128:   Not Collective

    130:   Input Parameter:
    131: . string - the name of the debugger, for example "gdb"

    133:   Level: developer

    135: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()`
    136: @*/
    137: PetscErrorCode PetscSetDebuggerFromString(const char string[])
    138: {
    139:   const char *debugger    = NULL;
    140:   PetscBool   useterminal = PETSC_TRUE;
    141:   char       *f           = NULL;

    143:   PetscFunctionBegin;
    144:   PetscCall(PetscStrstr(string, "noxterm", &f));
    145:   if (f) useterminal = PETSC_FALSE;
    146:   PetscCall(PetscStrstr(string, "ddd", &f));
    147:   if (f) useterminal = PETSC_FALSE;
    148:   PetscCall(PetscStrstr(string, "noterminal", &f));
    149:   if (f) useterminal = PETSC_FALSE;
    150:   PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
    151:   PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
    152:   PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
    153:   PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
    154:   PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
    155:   PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
    156:   PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
    157:   PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
    158:   PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
    159:   PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
    160:   PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
    161:   PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
    162:   PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
    163:   PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
    164:   PetscCall(PetscSetDebugger(debugger, useterminal));
    165:   PetscFunctionReturn(PETSC_SUCCESS);
    166: }

    168: /*@
    169:   PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
    170:   of exiting.

    172:   Not Collective

    174:   Level: advanced

    176:   Note:
    177:   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
    178:   killing the user's debugging sessions.

    180: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
    181: @*/
    182: PetscErrorCode PetscWaitOnError(void)
    183: {
    184:   petscwaitonerrorflg = PETSC_TRUE;
    185:   return PETSC_SUCCESS;
    186: }

    188: /*@
    189:   PetscAttachDebugger - Attaches the debugger to the running process.

    191:   Not Collective

    193:   Options Database Keys:
    194: + -start_in_debugger [noxterm,lldb or gdb] - Set debugger debug_terminal xterm or Terminal (for Apple)
    195: . -display name                            - XDisplay to open xterm in
    196: . -debugger_ranks m,n                      - Which MPI ranks on which to start the debugger, defaults to all
    197: . -stop_for_debugger                       - Print a message on how to attach the process with a debugger and then wait for the user to attach
    198: - -debugger_pause <secs>                   - Wait <secs> before attaching the debugger. This is useful for slow connections
    199:                                              that take a long time for the Terminal window or xterm to start up.

    201:   Level: advanced

    203:   Note:
    204:   If you get the message "`stdin` is not a `tty`, hence unable to attach debugger, see `PetscAttachDebugger()`", this means the application
    205:   is likely running in a batch system and you do not have terminal access to the process. You can try
    206:   running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger`

    208:   Developer Note:
    209:   Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?

    211: .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
    212: @*/
    213: PetscErrorCode PetscAttachDebugger(void)
    214: {
    215:   PetscErrorCode PETSC_UNUSED ierr;
    216: #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
    217:   int       child     = 0;
    218:   PetscReal sleeptime = 0;
    219:   char      program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
    220: #endif

    222: #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
    223:   ierr = (*PetscErrorPrintf)("System cannot start debugger\n");
    224:   ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
    225:   ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
    226:   PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
    227: #else
    228:   if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
    229:     ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n");
    230:     return PETSC_ERR_SYS;
    231:   }
    232:   if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
    233:     ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
    234:     return PETSC_ERR_SYS;
    235:   }
    236:   if (PetscUnlikely(!program[0])) {
    237:     ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
    238:     return PETSC_ERR_SYS;
    239:   }
    240:   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"); }
    241:   child = (int)fork();
    242:   if (PetscUnlikely(child < 0)) {
    243:     ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n");
    244:     return PETSC_ERR_SYS;
    245:   }
    246:   petscindebugger = PETSC_TRUE;

    248:   /*
    249:       Swap role the parent and child. This is (I think) so that control c typed
    250:     in the debugger goes to the correct process.
    251:   */
    252:   #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
    253:   child = child ? 0 : (int)getppid();
    254:   #endif

    256:   if (child) { /* I am the parent, will run the debugger */
    257:     const char *args[10];
    258:     char        pid[10];
    259:     PetscInt    j, jj;
    260:     PetscBool   isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;

    262:     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
    263:     /*
    264:          We need to send a continue signal to the "child" process on the
    265:        alpha, otherwise it just stays off forever
    266:     */
    267:   #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
    268:     kill(child, SIGCONT);
    269:   #endif
    270:     PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child));

    272:     PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
    273:     PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
    274:     PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
    275:     PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
    276:     PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
    277:     PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
    278:     PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
    279:     PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
    280:     PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
    281:     PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));

    283:     if (isxxgdb || isups || isddd) {
    284:       args[1] = program;
    285:       args[2] = pid;
    286:       args[3] = "-display";
    287:       args[0] = PetscDebugger;
    288:       args[4] = display;
    289:       args[5] = NULL;
    290:       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
    291:       if (execvp(args[0], (char **)args) < 0) {
    292:         perror("Unable to start debugger");
    293:         exit(0);
    294:       }
    295:     } else if (iskdbg) {
    296:       args[1] = "-p";
    297:       args[2] = pid;
    298:       args[3] = program;
    299:       args[4] = "-display";
    300:       args[0] = PetscDebugger;
    301:       args[5] = display;
    302:       args[6] = NULL;
    303:       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
    304:       if (execvp(args[0], (char **)args) < 0) {
    305:         perror("Unable to start debugger");
    306:         exit(0);
    307:       }
    308:     } else if (isxldb) {
    309:       args[1] = "-a";
    310:       args[2] = pid;
    311:       args[3] = program;
    312:       args[4] = "-display";
    313:       args[0] = PetscDebugger;
    314:       args[5] = display;
    315:       args[6] = NULL;
    316:       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
    317:       if (execvp(args[0], (char **)args) < 0) {
    318:         perror("Unable to start debugger");
    319:         exit(0);
    320:       }
    321:     } else if (isworkshop) {
    322:       args[1] = "-s";
    323:       args[2] = pid;
    324:       args[3] = "-D";
    325:       args[4] = "-";
    326:       args[0] = PetscDebugger;
    327:       args[5] = pid;
    328:       args[6] = "-display";
    329:       args[7] = display;
    330:       args[8] = NULL;
    331:       printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
    332:       if (execvp(args[0], (char **)args) < 0) {
    333:         perror("Unable to start debugger");
    334:         exit(0);
    335:       }
    336:     } else {
    337:       j = 0;
    338:       if (UseDebugTerminal) {
    339:         PetscBool cmp;
    340:         char     *tmp, *tmp1 = NULL;
    341:         PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
    342:         if (cmp) {
    343:           char command[1024];
    344:           if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s \"'\n", pid));
    345:           else {
    346:             char fullprogram[PETSC_MAX_PATH_LEN];
    347:             PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
    348:             PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s  %s %s \"'\n", PetscDebugger, fullprogram, pid));
    349:           }
    350:   #if defined(PETSC_HAVE_POPEN)
    351:           PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
    352:   #else
    353:           printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n");
    354:   #endif
    355:           exit(0);
    356:         }

    358:         PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
    359:         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
    360:         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
    361:         args[j++] = tmp = DebugTerminal;
    362:         if (display[0]) {
    363:           args[j++] = "-display";
    364:           args[j++] = display;
    365:         }
    366:         while (*tmp) {
    367:           PetscCall(PetscStrchr(tmp, ' ', &tmp1));
    368:           if (!tmp1) break;
    369:           *tmp1     = 0;
    370:           tmp       = tmp1 + 1;
    371:           args[j++] = tmp;
    372:         }
    373:       }
    374:       args[j++] = PetscDebugger;
    375:       jj        = j;
    376:       /* this is for default gdb */
    377:       args[j++] = program;
    378:       args[j++] = pid;
    379:       args[j++] = NULL;

    381:       if (isidb) {
    382:         j         = jj;
    383:         args[j++] = "-pid";
    384:         args[j++] = pid;
    385:         args[j++] = "-gdb";
    386:         args[j++] = program;
    387:         args[j++] = NULL;
    388:       }
    389:       if (islldb) {
    390:         j         = jj;
    391:         args[j++] = "-p";
    392:         args[j++] = pid;
    393:         args[j++] = NULL;
    394:       }
    395:       if (isdbx) {
    396:         j = jj;
    397:   #if defined(PETSC_USE_P_FOR_DEBUGGER)
    398:         args[j++] = "-p";
    399:         args[j++] = pid;
    400:         args[j++] = program;
    401:   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
    402:         args[j++] = "-l";
    403:         args[j++] = "ALL";
    404:         args[j++] = "-P";
    405:         args[j++] = pid;
    406:         args[j++] = program;
    407:   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
    408:         args[j++] = "-a";
    409:         args[j++] = pid;
    410:   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
    411:         args[j++] = "-pid";
    412:         args[j++] = pid;
    413:         args[j++] = program;
    414:   #else
    415:         args[j++] = program;
    416:         args[j++] = pid;
    417:   #endif
    418:         args[j++] = NULL;
    419:       }
    420:       if (UseDebugTerminal) {
    421:         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname);
    422:         else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);

    424:         if (execvp(args[0], (char **)args) < 0) {
    425:           perror("Unable to start debugger in xterm");
    426:           exit(0);
    427:         }
    428:       } else {
    429:         printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
    430:         if (execvp(args[0], (char **)args) < 0) {
    431:           perror("Unable to start debugger");
    432:           exit(0);
    433:         }
    434:       }
    435:     }
    436:   } else {          /* I am the child, continue with user code */
    437:     sleeptime = 10; /* default to sleep waiting for debugger */
    438:     PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
    439:     if (sleeptime < 0) sleeptime = -sleeptime;
    440:   #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
    441:     /*
    442:         HP cannot attach process to sleeping debugger, hence count instead
    443:     */
    444:     {
    445:       PetscReal x = 1.0;
    446:       int       i = 10000000;
    447:       while (i--) x++; /* cannot attach to sleeper */
    448:     }
    449:   #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
    450:     /*
    451:         IBM sleep may return at anytime, hence must see if there is more time to sleep
    452:     */
    453:     {
    454:       int left = sleeptime;
    455:       while (left > 0) left = PetscSleep(left) - 1;
    456:     }
    457:   #else
    458:     PetscCall(PetscSleep(sleeptime));
    459:   #endif
    460:   }
    461: #endif
    462:   return PETSC_SUCCESS;
    463: }

    465: /*@C
    466:   PetscAttachDebuggerErrorHandler - Error handler that attaches
    467:   a debugger to a running process when an error is detected.
    468:   This routine is useful for examining variables, etc.

    470:   Not Collective, No Fortran Support

    472:   Input Parameters:
    473: + comm - communicator over which error occurred
    474: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
    475: . fun  - the function name of the calling routine
    476: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
    477: . mess - an error text string, usually just printed to the screen
    478: . num  - the generic error number
    479: . p    - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
    480: - ctx  - error handler context

    482:   Level: developer

    484:   Notes:
    485:   By default the GNU debugger, gdb, is used except on macOS where lldb is used.  Alternatives are cuda-gdb, lldb, dbx and
    486:   xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).

    488:   Most users need not directly employ this routine and the other error
    489:   handlers, but can instead use the simplified interface SETERR, which has
    490:   the calling sequence
    491: .vb
    492:   SETERRQ(PETSC_COMM_SELF, number, p, message)
    493: .ve

    495:   Use `PetscPushErrorHandler()` to set the desired error handler.  The
    496:   currently available PETSc error handlers are
    497: .vb
    498:     PetscTraceBackErrorHandler()
    499:     PetscAttachDebuggerErrorHandler()
    500:     PetscAbortErrorHandler()
    501: .ve
    502:   or you may write your own.

    504:   Developer Note:
    505:   This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
    506:   causing the debugger to be attached again in a cycle.

    508: .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
    509:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
    510: @*/
    511: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
    512: {
    513:   (void)comm;
    514:   (void)num;
    515:   (void)p;
    516:   (void)ctx;
    517:   if (!mess) mess = " ";

    519:   if (fun) (void)(*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
    520:   else (void)(*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);

    522:   (void)PetscAttachDebugger();
    523:   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
    524:   PetscFunctionReturn(PETSC_SUCCESS);
    525: }

    527: /*@
    528:   PetscStopForDebugger - Prints a message to the screen indicating how to
    529:   attach to the process with the debugger and then waits for the
    530:   debugger to attach.

    532:   Not Collective, No Fortran Support

    534:   Options Database Key:
    535: . -stop_for_debugger - will stop for you to attach the debugger when `PetscInitialize()` is called

    537:   Level: developer

    539:   Note:
    540:   This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.

    542:   Developer Note:
    543:   Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?

    545: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
    546: @*/
    547: PetscErrorCode PetscStopForDebugger(void)
    548: {
    549:   PetscErrorCode ierr;
    550:   PetscInt       sleeptime = 0;
    551: #if !defined(PETSC_CANNOT_START_DEBUGGER)
    552:   int         ppid;
    553:   PetscMPIInt rank;
    554:   char        program[PETSC_MAX_PATH_LEN], hostname[256];
    555:   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
    556: #endif

    558:   PetscFunctionBegin;
    559: #if defined(PETSC_CANNOT_START_DEBUGGER)
    560:   PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
    561: #else
    562:   if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
    563:   ierr = PetscGetHostName(hostname, sizeof(hostname));
    564:   if (ierr) {
    565:     PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
    566:     PetscFunctionReturn(PETSC_SUCCESS);
    567:   }

    569:   ierr = PetscGetProgramName(program, sizeof(program));
    570:   if (ierr) {
    571:     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
    572:     PetscFunctionReturn(PETSC_SUCCESS);
    573:   }
    574:   if (!program[0]) {
    575:     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
    576:     PetscFunctionReturn(PETSC_SUCCESS);
    577:   }

    579:   ppid = getpid();

    581:   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
    582:   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
    583:   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
    584:   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
    585:   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
    586:   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
    587:   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
    588:   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));

    590:   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
    591:   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
    592:   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
    593:   else if (isdbx) {
    594:   #if defined(PETSC_USE_P_FOR_DEBUGGER)
    595:     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
    596:   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
    597:     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
    598:   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
    599:     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
    600:   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
    601:     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
    602:   #else
    603:     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
    604:   #endif
    605:   }
    606: #endif /* PETSC_CANNOT_START_DEBUGGER */

    608:   fflush(stdout); /* ignore error because may already be in error handler */

    610:   sleeptime = 25;                                                                         /* default to sleep waiting for debugger */
    611:   PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */
    612:   if (sleeptime < 0) sleeptime = -sleeptime;
    613: #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
    614:   /*
    615:       HP cannot attach process to sleeping debugger, hence count instead
    616:   */
    617:   {
    618:     // this *will* get optimized away by any compiler known to man
    619:     PetscReal x = 1.0;
    620:     int       i = 10000000;
    621:     while (i--) x++; /* cannot attach to sleeper */
    622:   }
    623: #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
    624:   /*
    625:       IBM sleep may return at anytime, hence must see if there is more time to sleep
    626:   */
    627:   {
    628:     int left = sleeptime;
    629:     while (left > 0) left = sleep(left) - 1;
    630:   }
    631: #else
    632:   PetscCall(PetscSleep(sleeptime));
    633: #endif
    634:   PetscFunctionReturn(PETSC_SUCCESS);
    635: }