xref: /petsc/src/sys/error/adebug.c (revision 66c9fbdd036b1e887ebf0d2bef6dbdcafd086d45)
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     sprintf(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           PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
335           exit(0);
336         }
337 
338         PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
339         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
340         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
341         args[j++] = tmp = DebugTerminal;
342         if (display[0]) {
343           args[j++] = "-display";
344           args[j++] = display;
345         }
346         while (*tmp) {
347           PetscCall(PetscStrchr(tmp, ' ', &tmp1));
348           if (!tmp1) break;
349           *tmp1     = 0;
350           tmp       = tmp1 + 1;
351           args[j++] = tmp;
352         }
353       }
354       args[j++] = PetscDebugger;
355       jj        = j;
356       /* this is for default gdb */
357       args[j++] = program;
358       args[j++] = pid;
359       args[j++] = NULL;
360 
361       if (isidb) {
362         j         = jj;
363         args[j++] = "-pid";
364         args[j++] = pid;
365         args[j++] = "-gdb";
366         args[j++] = program;
367         args[j++] = NULL;
368       }
369       if (islldb) {
370         j         = jj;
371         args[j++] = "-p";
372         args[j++] = pid;
373         args[j++] = NULL;
374       }
375       if (isdbx) {
376         j         = jj;
377   #if defined(PETSC_USE_P_FOR_DEBUGGER)
378         args[j++] = "-p";
379         args[j++] = pid;
380         args[j++] = program;
381   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
382         args[j++] = "-l";
383         args[j++] = "ALL";
384         args[j++] = "-P";
385         args[j++] = pid;
386         args[j++] = program;
387   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
388         args[j++] = "-a";
389         args[j++] = pid;
390   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
391         args[j++] = "-pid";
392         args[j++] = pid;
393         args[j++] = program;
394   #else
395         args[j++] = program;
396         args[j++] = pid;
397   #endif
398         args[j++] = NULL;
399       }
400       if (UseDebugTerminal) {
401         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n", PetscDebugger, program, pid, display, hostname);
402         else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);
403 
404         if (execvp(args[0], (char **)args) < 0) {
405           perror("Unable to start debugger in xterm");
406           exit(0);
407         }
408       } else {
409         printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
410         if (execvp(args[0], (char **)args) < 0) {
411           perror("Unable to start debugger");
412           exit(0);
413         }
414       }
415     }
416   } else {          /* I am the child, continue with user code */
417     sleeptime = 10; /* default to sleep waiting for debugger */
418     PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
419     if (sleeptime < 0) sleeptime = -sleeptime;
420   #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
421     /*
422         HP cannot attach process to sleeping debugger, hence count instead
423     */
424     {
425       PetscReal x = 1.0;
426       int       i = 10000000;
427       while (i--) x++; /* cannot attach to sleeper */
428     }
429   #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
430     /*
431         IBM sleep may return at anytime, hence must see if there is more time to sleep
432     */
433     {
434       int left = sleeptime;
435       while (left > 0) left = PetscSleep(left) - 1;
436     }
437   #else
438     PetscSleep(sleeptime);
439   #endif
440   }
441 #endif
442   return 0;
443 }
444 
445 /*@C
446    PetscAttachDebuggerErrorHandler - Error handler that attaches
447    a debugger to a running process when an error is detected.
448    This routine is useful for examining variables, etc.
449 
450    Not Collective
451 
452    Input Parameters:
453 +  comm - communicator over which error occurred
454 .  line - the line number of the error (indicated by __LINE__)
455 .  file - the file in which the error was detected (indicated by __FILE__)
456 .  message - an error text string, usually just printed to the screen
457 .  number - the generic error number
458 .  p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
459 -  ctx - error handler context
460 
461    Options Database Keys:
462 +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
463 -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
464 
465    Level: developer
466 
467    Notes:
468    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
469    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
470 
471    Most users need not directly employ this routine and the other error
472    handlers, but can instead use the simplified interface SETERR, which has
473    the calling sequence
474 $     SETERRQ(PETSC_COMM_SELF,number,p,message)
475 
476    Notes for experienced users:
477    Use `PetscPushErrorHandler()` to set the desired error handler.  The
478    currently available PETSc error handlers are
479 $    PetscTraceBackErrorHandler()
480 $    PetscAttachDebuggerErrorHandler()
481 $    PetscAbortErrorHandler()
482    or you may write your own.
483 
484    Developer Note:
485      This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
486      causing the debugger to be attached again in a cycle.
487 
488 .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
489           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
490 @*/
491 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
492 {
493   if (!mess) mess = " ";
494 
495   if (fun) (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
496   else (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
497 
498   PetscAttachDebugger();
499   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
500   PetscFunctionReturn(0);
501 }
502 
503 /*@C
504    PetscStopForDebugger - Prints a message to the screen indicating how to
505          attach to the process with the debugger and then waits for the
506          debugger to attach.
507 
508    Not Collective
509 
510    Options Database Key:
511 .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
512 
513    Level: developer
514 
515    Note:
516     This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
517 
518    Developer Note:
519     Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
520 
521 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
522 @*/
523 PetscErrorCode PetscStopForDebugger(void)
524 {
525   PetscErrorCode ierr;
526   PetscInt       sleeptime = 0;
527 #if !defined(PETSC_CANNOT_START_DEBUGGER)
528   int         ppid;
529   PetscMPIInt rank;
530   char        program[PETSC_MAX_PATH_LEN], hostname[256];
531   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
532 #endif
533 
534   PetscFunctionBegin;
535 #if defined(PETSC_CANNOT_START_DEBUGGER)
536   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
537 #else
538   ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
539   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
540   ierr = PetscGetHostName(hostname, sizeof(hostname));
541   if (ierr) {
542     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
543     PetscFunctionReturn(0);
544   }
545 
546   ierr = PetscGetProgramName(program, sizeof(program));
547   if (ierr) {
548     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
549     PetscFunctionReturn(0);
550   }
551   if (!program[0]) {
552     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
553     PetscFunctionReturn(0);
554   }
555 
556   ppid = getpid();
557 
558   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
559   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
560   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
561   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
562   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
563   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
564   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
565   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
566 
567   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
568   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
569   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
570   else if (isdbx) {
571   #if defined(PETSC_USE_P_FOR_DEBUGGER)
572     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
573   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
574     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
575   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
576     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
577   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
578     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
579   #else
580     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
581   #endif
582   }
583 #endif /* PETSC_CANNOT_START_DEBUGGER */
584 
585   fflush(stdout); /* ignore error because may already be in error handler */
586 
587   sleeptime = 25;                                                      /* default to sleep waiting for debugger */
588   PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL); /* ignore error because may already be in error handler */
589   if (sleeptime < 0) sleeptime = -sleeptime;
590 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
591   /*
592       HP cannot attach process to sleeping debugger, hence count instead
593   */
594   {
595     PetscReal x = 1.0;
596     int       i = 10000000;
597     while (i--) x++; /* cannot attach to sleeper */
598   }
599 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
600   /*
601       IBM sleep may return at anytime, hence must see if there is more time to sleep
602   */
603   {
604     int left = sleeptime;
605     while (left > 0) left = sleep(left) - 1;
606   }
607 #else
608   PetscSleep(sleeptime);
609 #endif
610   PetscFunctionReturn(0);
611 }
612