xref: /petsc/src/sys/error/adebug.c (revision 3307d110e72ee4e6d2468971620073eb5ff93529)
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           PetscCall(PetscSNPrintf(command,sizeof(command),"osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s  %s \"'\n",pid,program));
315           PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",NULL));
316           exit(0);
317         }
318 
319         PetscCall(PetscStrncmp(DebugTerminal,"screen",6,&cmp));
320         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp));
321         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
322         args[j++] = tmp = DebugTerminal;
323         if (display[0]) {
324           args[j++] = "-display"; args[j++] = display;
325         }
326         while (*tmp) {
327           PetscCall(PetscStrchr(tmp,' ',&tmp1));
328           if (!tmp1) break;
329           *tmp1     = 0;
330           tmp       = tmp1+1;
331           args[j++] = tmp;
332         }
333       }
334       args[j++] = PetscDebugger;
335       jj = j;
336       /* this is for default gdb */
337       args[j++] = program;
338       args[j++] = pid;
339       args[j++] = NULL;
340 
341       if (isidb) {
342         j = jj;
343         args[j++] = "-pid";
344         args[j++] = pid;
345         args[j++] = "-gdb";
346         args[j++] = program;
347         args[j++] = NULL;
348       }
349       if (islldb) {
350         j = jj;
351         args[j++] = "-p";
352         args[j++] = pid;
353         args[j++] = NULL;
354       }
355       if (isdbx) {
356         j = jj;
357 #if defined(PETSC_USE_P_FOR_DEBUGGER)
358         args[j++] = "-p";
359         args[j++] = pid;
360         args[j++] = program;
361 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
362         args[j++] = "-l";
363         args[j++] = "ALL";
364         args[j++] = "-P";
365         args[j++] = pid;
366         args[j++] = program;
367 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
368         args[j++] = "-a";
369         args[j++] = pid;
370 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
371         args[j++] = "-pid";
372         args[j++] = pid;
373         args[j++] = program;
374 #else
375         args[j++] = program;
376         args[j++] = pid;
377 #endif
378         args[j++] = NULL;
379       }
380       if (UseDebugTerminal) {
381         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",PetscDebugger,program,pid,display,hostname);
382         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
383 
384         if (execvp(args[0],(char**)args)  < 0) {
385           perror("Unable to start debugger in xterm");
386           exit(0);
387         }
388       } else {
389         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
390         if (execvp(args[0],(char**)args)  < 0) {
391           perror("Unable to start debugger");
392           exit(0);
393         }
394       }
395     }
396   } else {   /* I am the child, continue with user code */
397     sleeptime = 10; /* default to sleep waiting for debugger */
398     PetscCall(PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL));
399     if (sleeptime < 0) sleeptime = -sleeptime;
400 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
401     /*
402         HP cannot attach process to sleeping debugger, hence count instead
403     */
404     {
405       PetscReal x = 1.0;
406       int       i =10000000;
407       while (i--) x++;  /* cannot attach to sleeper */
408     }
409 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
410     /*
411         IBM sleep may return at anytime, hence must see if there is more time to sleep
412     */
413     {
414       int left = sleeptime;
415       while (left > 0) left = PetscSleep(left) - 1;
416     }
417 #else
418     PetscSleep(sleeptime);
419 #endif
420   }
421 #endif
422   PetscFunctionReturn(0);
423 }
424 
425 /*@C
426    PetscAttachDebuggerErrorHandler - Error handler that attaches
427    a debugger to a running process when an error is detected.
428    This routine is useful for examining variables, etc.
429 
430    Not Collective
431 
432    Input Parameters:
433 +  comm - communicator over which error occurred
434 .  line - the line number of the error (indicated by __LINE__)
435 .  file - the file in which the error was detected (indicated by __FILE__)
436 .  message - an error text string, usually just printed to the screen
437 .  number - the generic error number
438 .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
439 -  ctx - error handler context
440 
441    Options Database Keys:
442 +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
443 -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
444 
445    Level: developer
446 
447    Notes:
448    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
449    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
450 
451    Most users need not directly employ this routine and the other error
452    handlers, but can instead use the simplified interface SETERR, which has
453    the calling sequence
454 $     SETERRQ(PETSC_COMM_SELF,number,p,message)
455 
456    Notes for experienced users:
457    Use PetscPushErrorHandler() to set the desired error handler.  The
458    currently available PETSc error handlers are
459 $    PetscTraceBackErrorHandler()
460 $    PetscAttachDebuggerErrorHandler()
461 $    PetscAbortErrorHandler()
462    or you may write your own.
463 
464 .seealso:  PetscSetDebuggerFromString(), PetscSetDebugger(), PetscSetDefaultDebugger(), PetscError(), PetscPushErrorHandler(), PetscPopErrorHandler(), PetscTraceBackErrorHandler(),
465            PetscAbortErrorHandler(), PetscMPIAbortErrorHandler(), PetscEmacsClientErrorHandler(), PetscReturnErrorHandler(), PetscSetDebugTermainal()
466 @*/
467 PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
468 {
469   PetscErrorCode ierr;
470 
471   PetscFunctionBegin;
472   if (!fun) fun = "User provided function";
473   if (!mess) mess = " ";
474 
475   (*PetscErrorPrintf)("%s() at %s:%d %s\n",fun,file,line,mess);
476 
477   ierr = PetscAttachDebugger();
478   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
479   PetscFunctionReturn(0);
480 }
481 
482 /*@C
483    PetscStopForDebugger - Prints a message to the screen indicating how to
484          attach to the process with the debugger and then waits for the
485          debugger to attach.
486 
487    Not Collective
488 
489    Options Database:
490 .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
491 
492    Level: developer
493 
494    Notes:
495     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
496 
497    Developer Notes:
498     Since this can be called by the error handler, should it be calling SETERRQ() and PetscCall()?
499 
500 .seealso: PetscSetDebugger(), PetscAttachDebugger()
501 @*/
502 PetscErrorCode  PetscStopForDebugger(void)
503 {
504   PetscErrorCode ierr;
505   PetscInt       sleeptime=0;
506 #if !defined(PETSC_CANNOT_START_DEBUGGER)
507   int            ppid;
508   PetscMPIInt    rank;
509   char           program[PETSC_MAX_PATH_LEN],hostname[256];
510   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
511 #endif
512 
513   PetscFunctionBegin;
514 #if defined(PETSC_CANNOT_START_DEBUGGER)
515   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
516 #else
517   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
518   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
519   ierr = PetscGetHostName(hostname,sizeof(hostname));
520   if (ierr) {
521     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
522     PetscFunctionReturn(0);
523   }
524 
525   ierr = PetscGetProgramName(program,sizeof(program));
526   if (ierr) {
527     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
528     PetscFunctionReturn(0);
529   }
530   if (!program[0]) {
531     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
532     PetscFunctionReturn(0);
533   }
534 
535   ppid = getpid();
536 
537   PetscCall(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
538   PetscCall(PetscStrcmp(PetscDebugger,"ddd",&isddd));
539   PetscCall(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
540   PetscCall(PetscStrcmp(PetscDebugger,"ups",&isups));
541   PetscCall(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
542   PetscCall(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
543   PetscCall(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
544   PetscCall(PetscStrcmp(PetscDebugger,"lldb",&islldb));
545 
546   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
547   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
548   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
549   else if (isdbx) {
550 #if defined(PETSC_USE_P_FOR_DEBUGGER)
551      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
552 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
553      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
554 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
555      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
556 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
557      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
558 #else
559      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
560 #endif
561   }
562 #endif /* PETSC_CANNOT_START_DEBUGGER */
563 
564   fflush(stdout); /* ignore error because may already be in error handler */
565 
566   sleeptime = 25; /* default to sleep waiting for debugger */
567   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
568   if (sleeptime < 0) sleeptime = -sleeptime;
569 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
570   /*
571       HP cannot attach process to sleeping debugger, hence count instead
572   */
573   {
574     PetscReal x = 1.0;
575     int       i =10000000;
576     while (i--) x++;  /* cannot attach to sleeper */
577   }
578 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
579   /*
580       IBM sleep may return at anytime, hence must see if there is more time to sleep
581   */
582   {
583     int left = sleeptime;
584     while (left > 0) left = sleep(left) - 1;
585   }
586 #else
587   PetscSleep(sleeptime);
588 #endif
589   PetscFunctionReturn(0);
590 }
591