Actual source code: adebug.c

  1: /*
  2:       Code to handle PETSc starting up in debuggers,etc.
  3: */

  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()`
 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()`
 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:    Level: developer

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;

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

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.

168:    Not Collective

170:    Level: advanced

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.

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

184: /*@
185:    PetscAttachDebugger - Attaches the debugger to the running process.

187:    Not Collective

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

193:    Level: advanced

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

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

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;

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

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;

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

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

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

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;

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

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

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.

456:    Not Collective

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

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]

471:    Level: developer

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

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)

482:    Notes for experienced users:
483:    Use `PetscPushErrorHandler()` to set the desired error handler.  The
484:    currently available PETSc error handlers are
485: .vb
486:     PetscTraceBackErrorHandler()
487:     PetscAttachDebuggerErrorHandler()
488:     PetscAbortErrorHandler()
489: .ve
490:   or you may write your own.

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

496: .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
497:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
498: @*/
499: PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
500: {
501:   PetscErrorCode ierr;
502:   if (!mess) mess = " ";

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

507:   ierr = PetscAttachDebugger();
508:   (void)ierr;
509:   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
510:   PetscFunctionReturn(PETSC_SUCCESS);
511: }

513: /*@C
514:    PetscStopForDebugger - Prints a message to the screen indicating how to
515:          attach to the process with the debugger and then waits for the
516:          debugger to attach.

518:    Not Collective

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

523:    Level: developer

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

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

531: .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
532: @*/
533: PetscErrorCode PetscStopForDebugger(void)
534: {
535:   PetscErrorCode ierr;
536:   PetscInt       sleeptime = 0;
537: #if !defined(PETSC_CANNOT_START_DEBUGGER)
538:   int         ppid;
539:   PetscMPIInt rank;
540:   char        program[PETSC_MAX_PATH_LEN], hostname[256];
541:   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
542: #endif

544:   PetscFunctionBegin;
545: #if defined(PETSC_CANNOT_START_DEBUGGER)
546:   PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
547: #else
548:   if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
549:   ierr = PetscGetHostName(hostname, sizeof(hostname));
550:   if (ierr) {
551:     PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
552:     PetscFunctionReturn(PETSC_SUCCESS);
553:   }

555:   ierr = PetscGetProgramName(program, sizeof(program));
556:   if (ierr) {
557:     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
558:     PetscFunctionReturn(PETSC_SUCCESS);
559:   }
560:   if (!program[0]) {
561:     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
562:     PetscFunctionReturn(PETSC_SUCCESS);
563:   }

565:   ppid = getpid();

567:   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
568:   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
569:   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
570:   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
571:   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
572:   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
573:   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
574:   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));

576:   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
577:   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
578:   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
579:   else if (isdbx) {
580:   #if defined(PETSC_USE_P_FOR_DEBUGGER)
581:     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
582:   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
583:     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
584:   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
585:     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
586:   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
587:     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
588:   #else
589:     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
590:   #endif
591:   }
592: #endif /* PETSC_CANNOT_START_DEBUGGER */

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

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