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