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: /*@C
 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.

 38: $     mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"

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

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

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

 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: }

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

 60:   Not Collective; No Fortran Support

 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".

 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.)

 72:   Level: developer

 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: }

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

 87:   Not Collective

 89:   Level: developer

 91: .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()`
 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: }

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

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

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

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

127:   Not Collective

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

132:   Level: developer

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

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

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

171:   Not Collective

173:   Level: advanced

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

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

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

190:   Not Collective

192:   Options Database Keys:
193: + -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] - set debugger debug_terminal xterm or Terminal (for Apple)
194: . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name]                - Activates debugger attachment
195: - -stop_for_debugger                                                                        - print a message on how to attach the process with a debugger and then wait for the user to attach

197:   Level: advanced

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

204:   Developer Notes:
205:   Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?

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

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

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

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

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

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

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

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

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

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

461: /*@C
462:   PetscAttachDebuggerErrorHandler - Error handler that attaches
463:   a debugger to a running process when an error is detected.
464:   This routine is useful for examining variables, etc.

466:   Not Collective

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

478:   Level: developer

480:   Notes:
481:   By default the Gnu debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
482:   xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).

484:   Most users need not directly employ this routine and the other error
485:   handlers, but can instead use the simplified interface SETERR, which has
486:   the calling sequence
487: $     SETERRQ(PETSC_COMM_SELF, number, p, message)

489:   Notes for experienced users:
490:   Use `PetscPushErrorHandler()` to set the desired error handler.  The
491:   currently available PETSc error handlers are
492: .vb
493:     PetscTraceBackErrorHandler()
494:     PetscAttachDebuggerErrorHandler()
495:     PetscAbortErrorHandler()
496: .ve
497:   or you may write your own.

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

503: .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
504:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
505: @*/
506: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
507: {
508:   PetscErrorCode ierr;

510:   (void)comm;
511:   (void)num;
512:   (void)p;
513:   (void)ctx;
514:   if (!mess) mess = " ";

516:   if (fun) ierr = (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
517:   else ierr = (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);

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

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

530:   Not Collective

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

535:   Level: developer

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

540:   Developer Notes:
541:   Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?

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

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

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

577:   ppid = getpid();

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

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

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

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