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