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