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