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