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