xref: /petsc/src/sys/error/adebug.c (revision 73fdd05bb67e49f40fd8fd311695ff6fdf0b9b8a)
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; 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()`
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()`
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()`
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] -debug_terminal xterm or Terminal (for Apple)
191 .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
192 
193    Level: advanced
194 
195    Developer Note:
196     Since this can be called by the error handler should it be calling `SETERRQ()` and `PetscCall()`?
197 
198 .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
199 @*/
200 PetscErrorCode PetscAttachDebugger(void)
201 {
202   PetscErrorCode PETSC_UNUSED ierr;
203 #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
204   int       child     = 0;
205   PetscReal sleeptime = 0;
206   char      program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
207 #endif
208 
209 #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
210   ierr = (*PetscErrorPrintf)("System cannot start debugger\n");
211   ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
212   ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
213   PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
214 #else
215   if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
216     ierr = (*PetscErrorPrintf)("Cannot determine display\n");
217     return PETSC_ERR_SYS;
218   }
219   if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
220     ierr = (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
221     return PETSC_ERR_SYS;
222   }
223   if (PetscUnlikely(!program[0])) {
224     ierr = (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
225     return PETSC_ERR_SYS;
226   }
227   child = (int)fork();
228   if (PetscUnlikely(child < 0)) {
229     ierr = (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
230     return PETSC_ERR_SYS;
231   }
232   petscindebugger = PETSC_TRUE;
233 
234   /*
235       Swap role the parent and child. This is (I think) so that control c typed
236     in the debugger goes to the correct process.
237   */
238   #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
239   child = child ? 0 : (int)getppid();
240   #endif
241 
242   if (child) { /* I am the parent, will run the debugger */
243     const char *args[10];
244     char        pid[10];
245     PetscInt    j, jj;
246     PetscBool   isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
247 
248     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
249     /*
250          We need to send a continue signal to the "child" process on the
251        alpha, otherwise it just stays off forever
252     */
253   #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
254     kill(child, SIGCONT);
255   #endif
256     PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child));
257 
258     PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
259     PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
260     PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
261     PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
262     PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
263     PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
264     PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
265     PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
266     PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
267     PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
268 
269     if (isxxgdb || isups || isddd) {
270       args[1] = program;
271       args[2] = pid;
272       args[3] = "-display";
273       args[0] = PetscDebugger;
274       args[4] = display;
275       args[5] = NULL;
276       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
277       if (execvp(args[0], (char **)args) < 0) {
278         perror("Unable to start debugger");
279         exit(0);
280       }
281     } else if (iskdbg) {
282       args[1] = "-p";
283       args[2] = pid;
284       args[3] = program;
285       args[4] = "-display";
286       args[0] = PetscDebugger;
287       args[5] = display;
288       args[6] = NULL;
289       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
290       if (execvp(args[0], (char **)args) < 0) {
291         perror("Unable to start debugger");
292         exit(0);
293       }
294     } else if (isxldb) {
295       args[1] = "-a";
296       args[2] = pid;
297       args[3] = program;
298       args[4] = "-display";
299       args[0] = PetscDebugger;
300       args[5] = display;
301       args[6] = NULL;
302       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
303       if (execvp(args[0], (char **)args) < 0) {
304         perror("Unable to start debugger");
305         exit(0);
306       }
307     } else if (isworkshop) {
308       args[1] = "-s";
309       args[2] = pid;
310       args[3] = "-D";
311       args[4] = "-";
312       args[0] = PetscDebugger;
313       args[5] = pid;
314       args[6] = "-display";
315       args[7] = display;
316       args[8] = NULL;
317       printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
318       if (execvp(args[0], (char **)args) < 0) {
319         perror("Unable to start debugger");
320         exit(0);
321       }
322     } else {
323       j = 0;
324       if (UseDebugTerminal) {
325         PetscBool cmp;
326         char     *tmp, *tmp1 = NULL;
327         PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
328         if (cmp) {
329           char command[1024];
330           if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s \"'\n", pid));
331           else {
332             char fullprogram[PETSC_MAX_PATH_LEN];
333             PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
334             PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s  %s %s \"'\n", PetscDebugger, fullprogram, pid));
335           }
336   #if defined(PETSC_HAVE_POPEN)
337           PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
338   #else
339           printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n");
340   #endif
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     PetscCall(PetscSleep(sleeptime));
445   #endif
446   }
447 #endif
448   return PETSC_SUCCESS;
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   PetscErrorCode ierr;
500   if (!mess) mess = " ";
501 
502   if (fun) ierr = (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
503   else ierr = (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
504 
505   ierr = PetscAttachDebugger();
506   (void)ierr;
507   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
508   PetscFunctionReturn(PETSC_SUCCESS);
509 }
510 
511 /*@C
512    PetscStopForDebugger - Prints a message to the screen indicating how to
513          attach to the process with the debugger and then waits for the
514          debugger to attach.
515 
516    Not Collective
517 
518    Options Database Key:
519 .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
520 
521    Level: developer
522 
523    Note:
524     This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
525 
526    Developer Note:
527     Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
528 
529 .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
530 @*/
531 PetscErrorCode PetscStopForDebugger(void)
532 {
533   PetscErrorCode ierr;
534   PetscInt       sleeptime = 0;
535 #if !defined(PETSC_CANNOT_START_DEBUGGER)
536   int         ppid;
537   PetscMPIInt rank;
538   char        program[PETSC_MAX_PATH_LEN], hostname[256];
539   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
540 #endif
541 
542   PetscFunctionBegin;
543 #if defined(PETSC_CANNOT_START_DEBUGGER)
544   PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
545 #else
546   if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
547   ierr = PetscGetHostName(hostname, sizeof(hostname));
548   if (ierr) {
549     PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
550     PetscFunctionReturn(PETSC_SUCCESS);
551   }
552 
553   ierr = PetscGetProgramName(program, sizeof(program));
554   if (ierr) {
555     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
556     PetscFunctionReturn(PETSC_SUCCESS);
557   }
558   if (!program[0]) {
559     PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
560     PetscFunctionReturn(PETSC_SUCCESS);
561   }
562 
563   ppid = getpid();
564 
565   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
566   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
567   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
568   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
569   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
570   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
571   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
572   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
573 
574   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
575   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
576   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
577   else if (isdbx) {
578   #if defined(PETSC_USE_P_FOR_DEBUGGER)
579     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
580   #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
581     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
582   #elif defined(PETSC_USE_A_FOR_DEBUGGER)
583     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
584   #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
585     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
586   #else
587     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
588   #endif
589   }
590 #endif /* PETSC_CANNOT_START_DEBUGGER */
591 
592   fflush(stdout); /* ignore error because may already be in error handler */
593 
594   sleeptime = 25;                                                                         /* default to sleep waiting for debugger */
595   PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */
596   if (sleeptime < 0) sleeptime = -sleeptime;
597 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
598   /*
599       HP cannot attach process to sleeping debugger, hence count instead
600   */
601   {
602     // this *will* get optimized away by any compiler known to man
603     PetscReal x = 1.0;
604     int       i = 10000000;
605     while (i--) x++; /* cannot attach to sleeper */
606   }
607 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
608   /*
609       IBM sleep may return at anytime, hence must see if there is more time to sleep
610   */
611   {
612     int left = sleeptime;
613     while (left > 0) left = sleep(left) - 1;
614   }
615 #else
616   PetscCall(PetscSleep(sleeptime));
617 #endif
618   PetscFunctionReturn(PETSC_SUCCESS);
619 }
620