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