xref: /petsc/src/sys/error/adebug.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 SETERRQ() and 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   PetscFunctionBegin;
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     PetscFunctionReturn(PETSC_ERR_SYS);
216   }
217   if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
218     (*PetscErrorPrintf)("Cannot determine program name\n");
219     PetscFunctionReturn(PETSC_ERR_SYS);
220   }
221   if (PetscUnlikely(!program[0])) {
222     (*PetscErrorPrintf)("Cannot determine program name\n");
223     PetscFunctionReturn(PETSC_ERR_SYS);
224   }
225   child = (int)fork();
226   if (PetscUnlikely(child < 0)) {
227     (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
228     PetscFunctionReturn(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   PetscFunctionReturn(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 Notes:
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   PetscFunctionBegin;
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 processes 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:
511 .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
512 
513    Level: developer
514 
515    Notes:
516     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
517 
518    Developer Notes:
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   PetscErrorCode ierr;
525   PetscInt       sleeptime = 0;
526 #if !defined(PETSC_CANNOT_START_DEBUGGER)
527   int         ppid;
528   PetscMPIInt rank;
529   char        program[PETSC_MAX_PATH_LEN], hostname[256];
530   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
531 #endif
532 
533   PetscFunctionBegin;
534 #if defined(PETSC_CANNOT_START_DEBUGGER)
535   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
536 #else
537   ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
538   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
539   ierr = PetscGetHostName(hostname, sizeof(hostname));
540   if (ierr) {
541     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
542     PetscFunctionReturn(0);
543   }
544 
545   ierr = PetscGetProgramName(program, sizeof(program));
546   if (ierr) {
547     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
548     PetscFunctionReturn(0);
549   }
550   if (!program[0]) {
551     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
552     PetscFunctionReturn(0);
553   }
554 
555   ppid = getpid();
556 
557   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
558   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
559   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
560   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
561   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
562   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
563   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
564   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
565 
566   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
567   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
568   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
569   else if (isdbx) {
570 #if defined(PETSC_USE_P_FOR_DEBUGGER)
571     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
572 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
573     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
574 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
575     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
576 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
577     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
578 #else
579     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
580 #endif
581   }
582 #endif /* PETSC_CANNOT_START_DEBUGGER */
583 
584   fflush(stdout); /* ignore error because may already be in error handler */
585 
586   sleeptime = 25;                                                      /* default to sleep waiting for debugger */
587   PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL); /* ignore error because may already be in error handler */
588   if (sleeptime < 0) sleeptime = -sleeptime;
589 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
590   /*
591       HP cannot attach process to sleeping debugger, hence count instead
592   */
593   {
594     PetscReal x = 1.0;
595     int       i = 10000000;
596     while (i--) x++; /* cannot attach to sleeper */
597   }
598 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
599   /*
600       IBM sleep may return at anytime, hence must see if there is more time to sleep
601   */
602   {
603     int left = sleeptime;
604     while (left > 0) left = sleep(left) - 1;
605   }
606 #else
607   PetscSleep(sleeptime);
608 #endif
609   PetscFunctionReturn(0);
610 }
611