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