xref: /petsc/src/sys/error/adebug.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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 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    Fortran Note:
45    This routine is not supported in Fortran.
46 
47 .seealso: `PetscSetDebugger()`
48 @*/
49 PetscErrorCode PetscSetDebugTerminal(const char terminal[])
50 {
51   PetscBool xterm;
52 
53   PetscFunctionBegin;
54   PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal)));
55   PetscCall(PetscStrcmp(terminal, "xterm", &xterm));
56   if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal)));
57   PetscFunctionReturn(0);
58 }
59 
60 /*@C
61    PetscSetDebugger - Sets options associated with the debugger.
62 
63    Not Collective
64 
65    Input Parameters:
66 +  debugger - name of debugger, which should be in your path,
67               usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
68               supports "xdb", and IBM rs6000 supports "xldb".
69 
70 -  usedebugterminal - flag to indicate debugger window, set to either PETSC_TRUE (to indicate
71             debugger should be started in a new terminal window) or PETSC_FALSE (to start debugger
72             in initial window (the option PETSC_FALSE makes no sense when using more
73             than one MPI process.)
74 
75    Level: developer
76 
77    Fortran Note:
78    This routine is not supported in Fortran.
79 
80 .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
81 @*/
82 PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
83 {
84   PetscFunctionBegin;
85   if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger)));
86   if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
87   PetscFunctionReturn(0);
88 }
89 
90 /*@C
91     PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
92 
93    Not collective
94 
95     Level: developer
96 
97 .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`
98 @*/
99 PetscErrorCode PetscSetDefaultDebugger(void)
100 {
101   PetscFunctionBegin;
102 #if defined(PETSC_USE_DEBUGGER)
103   PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE));
104 #endif
105 #if defined(__APPLE__)
106   PetscCall(PetscSetDebugTerminal("Terminal"));
107 #else
108   PetscCall(PetscSetDebugTerminal("xterm"));
109 #endif
110   PetscFunctionReturn(0);
111 }
112 
113 static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
114 {
115   PetscBool exists;
116   char     *f;
117 
118   PetscFunctionBegin;
119   PetscCall(PetscStrstr(string, defaultDbg, &f));
120   if (f) {
121     PetscCall(PetscTestFile(string, 'x', &exists));
122     if (exists) *debugger = string;
123     else *debugger = defaultDbg;
124   }
125   PetscFunctionReturn(0);
126 }
127 
128 /*@C
129     PetscSetDebuggerFromString - Set the complete path for the
130        debugger for PETSc to use.
131 
132    Not collective
133 
134    Level: developer
135 
136 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`
137 @*/
138 PetscErrorCode PetscSetDebuggerFromString(const char *string)
139 {
140   const char *debugger    = NULL;
141   PetscBool   useterminal = PETSC_TRUE;
142   char       *f;
143 
144   PetscFunctionBegin;
145   PetscCall(PetscStrstr(string, "noxterm", &f));
146   if (f) useterminal = PETSC_FALSE;
147   PetscCall(PetscStrstr(string, "ddd", &f));
148   if (f) useterminal = PETSC_FALSE;
149   PetscCall(PetscStrstr(string, "noterminal", &f));
150   if (f) useterminal = PETSC_FALSE;
151   PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
152   PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
153   PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
154   PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
155   PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
156   PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
157   PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
158   PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
159   PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
160   PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
161   PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
162   PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
163   PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
164   PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
165   PetscCall(PetscSetDebugger(debugger, useterminal));
166   PetscFunctionReturn(0);
167 }
168 
169 /*@
170    PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
171                       of exiting.
172 
173    Not Collective
174 
175    Level: advanced
176 
177    Note:
178       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
179       killing the user's debugging sessions.
180 
181 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
182 @*/
183 PetscErrorCode PetscWaitOnError()
184 {
185   petscwaitonerrorflg = PETSC_TRUE;
186   return 0;
187 }
188 
189 /*@
190    PetscAttachDebugger - Attaches the debugger to the running process.
191 
192    Not Collective
193 
194    Options Database Keys:
195 -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] -debug_terminal xterm or Terminal (for Apple)
196 .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
197 
198    Level: advanced
199 
200    Developer Note:
201     Since this can be called by the error handler should it be calling `SETERRQ()` and `PetscCall()`?
202 
203 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
204 @*/
205 PetscErrorCode PetscAttachDebugger(void)
206 {
207 #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
208   int       child     = 0;
209   PetscReal sleeptime = 0;
210   char      program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
211 #endif
212 
213 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
214   (*PetscErrorPrintf)("System cannot start debugger\n");
215   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
216   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
217   PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
218 #else
219   if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
220     (*PetscErrorPrintf)("Cannot determine display\n");
221     return PETSC_ERR_SYS;
222   }
223   if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
224     (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
225     return PETSC_ERR_SYS;
226   }
227   if (PetscUnlikely(!program[0])) {
228     (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
229     return PETSC_ERR_SYS;
230   }
231   child = (int)fork();
232   if (PetscUnlikely(child < 0)) {
233     (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
234     return PETSC_ERR_SYS;
235   }
236   petscindebugger = PETSC_TRUE;
237 
238   /*
239       Swap role the parent and child. This is (I think) so that control c typed
240     in the debugger goes to the correct process.
241   */
242   #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
243   child = child ? 0 : (int)getppid();
244   #endif
245 
246   if (child) { /* I am the parent, will run the debugger */
247     const char *args[10];
248     char        pid[10];
249     PetscInt    j, jj;
250     PetscBool   isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
251 
252     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
253     /*
254          We need to send a continue signal to the "child" process on the
255        alpha, otherwise it just stays off forever
256     */
257   #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
258     kill(child, SIGCONT);
259   #endif
260     sprintf(pid, "%d", child);
261 
262     PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
263     PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
264     PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
265     PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
266     PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
267     PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
268     PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
269     PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
270     PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
271     PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
272 
273     if (isxxgdb || isups || isddd) {
274       args[1] = program;
275       args[2] = pid;
276       args[3] = "-display";
277       args[0] = PetscDebugger;
278       args[4] = display;
279       args[5] = NULL;
280       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
281       if (execvp(args[0], (char **)args) < 0) {
282         perror("Unable to start debugger");
283         exit(0);
284       }
285     } else if (iskdbg) {
286       args[1] = "-p";
287       args[2] = pid;
288       args[3] = program;
289       args[4] = "-display";
290       args[0] = PetscDebugger;
291       args[5] = display;
292       args[6] = NULL;
293       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
294       if (execvp(args[0], (char **)args) < 0) {
295         perror("Unable to start debugger");
296         exit(0);
297       }
298     } else if (isxldb) {
299       args[1] = "-a";
300       args[2] = pid;
301       args[3] = program;
302       args[4] = "-display";
303       args[0] = PetscDebugger;
304       args[5] = display;
305       args[6] = NULL;
306       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
307       if (execvp(args[0], (char **)args) < 0) {
308         perror("Unable to start debugger");
309         exit(0);
310       }
311     } else if (isworkshop) {
312       args[1] = "-s";
313       args[2] = pid;
314       args[3] = "-D";
315       args[4] = "-";
316       args[0] = PetscDebugger;
317       args[5] = pid;
318       args[6] = "-display";
319       args[7] = display;
320       args[8] = NULL;
321       printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
322       if (execvp(args[0], (char **)args) < 0) {
323         perror("Unable to start debugger");
324         exit(0);
325       }
326     } else {
327       j = 0;
328       if (UseDebugTerminal) {
329         PetscBool cmp;
330         char     *tmp, *tmp1;
331         PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
332         if (cmp) {
333           char command[1024];
334           if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s \"'\n", pid));
335           else {
336             char fullprogram[PETSC_MAX_PATH_LEN];
337             PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
338             PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s  %s %s \"'\n", PetscDebugger, fullprogram, pid));
339           }
340           PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
341           exit(0);
342         }
343 
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;
366 
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);
409 
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     PetscSleep(sleeptime);
445   #endif
446   }
447 #endif
448   return 0;
449 }
450 
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.
455 
456    Not Collective
457 
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
466 
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]
470 
471    Level: developer
472 
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).
476 
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)
481 
482    Notes for experienced users:
483    Use `PetscPushErrorHandler()` to set the desired error handler.  The
484    currently available PETSc error handlers are
485 $    PetscTraceBackErrorHandler()
486 $    PetscAttachDebuggerErrorHandler()
487 $    PetscAbortErrorHandler()
488    or you may write your own.
489 
490    Developer Note:
491      This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
492      causing the debugger to be attached again in a cycle.
493 
494 .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
495           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
496 @*/
497 PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx)
498 {
499   if (!mess) mess = " ";
500 
501   if (fun) (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
502   else (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
503 
504   PetscAttachDebugger();
505   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
506   PetscFunctionReturn(0);
507 }
508 
509 /*@C
510    PetscStopForDebugger - Prints a message to the screen indicating how to
511          attach to the process with the debugger and then waits for the
512          debugger to attach.
513 
514    Not Collective
515 
516    Options Database Key:
517 .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
518 
519    Level: developer
520 
521    Note:
522     This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
523 
524    Developer Note:
525     Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
526 
527 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
528 @*/
529 PetscErrorCode PetscStopForDebugger(void)
530 {
531   PetscErrorCode ierr;
532   PetscInt       sleeptime = 0;
533 #if !defined(PETSC_CANNOT_START_DEBUGGER)
534   int         ppid;
535   PetscMPIInt rank;
536   char        program[PETSC_MAX_PATH_LEN], hostname[256];
537   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
538 #endif
539 
540   PetscFunctionBegin;
541 #if defined(PETSC_CANNOT_START_DEBUGGER)
542   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
543 #else
544   ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
545   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
546   ierr = PetscGetHostName(hostname, sizeof(hostname));
547   if (ierr) {
548     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
549     PetscFunctionReturn(0);
550   }
551 
552   ierr = PetscGetProgramName(program, sizeof(program));
553   if (ierr) {
554     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
555     PetscFunctionReturn(0);
556   }
557   if (!program[0]) {
558     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
559     PetscFunctionReturn(0);
560   }
561 
562   ppid = getpid();
563 
564   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
565   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
566   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
567   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
568   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
569   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
570   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
571   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
572 
573   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
574   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
575   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
576   else if (isdbx) {
577   #if defined(PETSC_USE_P_FOR_DEBUGGER)
578     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
579   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
580     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
581   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
582     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
583   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
584     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
585   #else
586     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
587   #endif
588   }
589 #endif /* PETSC_CANNOT_START_DEBUGGER */
590 
591   fflush(stdout); /* ignore error because may already be in error handler */
592 
593   sleeptime = 25;                                                      /* default to sleep waiting for debugger */
594   PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL); /* ignore error because may already be in error handler */
595   if (sleeptime < 0) sleeptime = -sleeptime;
596 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
597   /*
598       HP cannot attach process to sleeping debugger, hence count instead
599   */
600   {
601     PetscReal x = 1.0;
602     int       i = 10000000;
603     while (i--) x++; /* cannot attach to sleeper */
604   }
605 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
606   /*
607       IBM sleep may return at anytime, hence must see if there is more time to sleep
608   */
609   {
610     int left = sleeptime;
611     while (left > 0) left = sleep(left) - 1;
612   }
613 #else
614   PetscSleep(sleeptime);
615 #endif
616   PetscFunctionReturn(0);
617 }
618