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