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