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