xref: /petsc/src/sys/error/adebug.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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".
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) display[0] = 0; /* when using screen, we never pass -display */
295         args[j++] = tmp = DebugTerminal;
296         if (display[0]) {
297           args[j++] = "-display"; args[j++] = display;
298         }
299         while (*tmp) {
300           ierr = PetscStrchr(tmp,' ',&tmp1);CHKERRQ(ierr);
301           if (!tmp1) break;
302           *tmp1     = 0;
303           tmp       = tmp1+1;
304           args[j++] = tmp;
305         }
306       }
307       args[j++] = PetscDebugger;
308       jj = j;
309       args[j++] = program; args[j++] = pid; args[j++] = 0;
310 
311       if (isidb) {
312         j = jj;
313         args[j++] = "-pid";
314         args[j++] = pid;
315         args[j++] = "-gdb";
316         args[j++] = program;
317         args[j++] = 0;
318       }
319       if (islldb) {
320         j = jj;
321         args[j++] = "-p";
322         args[j++] = pid;
323         args[j++] = 0;
324       }
325       if (isdbx) {
326         j = jj;
327 #if defined(PETSC_USE_P_FOR_DEBUGGER)
328         args[j++] = "-p";
329         args[j++] = pid;
330         args[j++] = program;
331 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
332         args[j++] = "-l";
333         args[j++] = "ALL";
334         args[j++] = "-P";
335         args[j++] = pid;
336         args[j++] = program;
337 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
338         args[j++] = "-a";
339         args[j++] = pid;
340 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
341         args[j++] = "-pid";
342         args[j++] = pid;
343         args[j++] = program;
344 #else
345         args[j++] = program;
346         args[j++] = pid;
347 #endif
348         args[j++] = 0;
349       }
350       if (Xterm) {
351         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",PetscDebugger,program,pid,display,hostname);
352         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
353 
354         if (execvp(args[0],(char**)args)  < 0) {
355           perror("Unable to start debugger in xterm");
356           exit(0);
357         }
358       } else {
359         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
360         if (execvp(args[0],(char**)args)  < 0) {
361           perror("Unable to start debugger");
362           exit(0);
363         }
364       }
365     }
366   } else {   /* I am the child, continue with user code */
367     sleeptime = 10; /* default to sleep waiting for debugger */
368     ierr = PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL);CHKERRQ(ierr);
369     if (sleeptime < 0) sleeptime = -sleeptime;
370 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
371     /*
372         HP cannot attach process to sleeping debugger, hence count instead
373     */
374     {
375       PetscReal x = 1.0;
376       int       i =10000000;
377       while (i--) x++;  /* cannot attach to sleeper */
378     }
379 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
380     /*
381         IBM sleep may return at anytime, hence must see if there is more time to sleep
382     */
383     {
384       int left = sleeptime;
385       while (left > 0) left = PetscSleep(left) - 1;
386     }
387 #else
388     PetscSleep(sleeptime);
389 #endif
390   }
391 #endif
392   PetscFunctionReturn(0);
393 }
394 
395 /*@C
396    PetscAttachDebuggerErrorHandler - Error handler that attaches
397    a debugger to a running process when an error is detected.
398    This routine is useful for examining variables, etc.
399 
400    Not Collective
401 
402    Input Parameters:
403 +  comm - communicator over which error occurred
404 .  line - the line number of the error (indicated by __LINE__)
405 .  file - the file in which the error was detected (indicated by __FILE__)
406 .  message - an error text string, usually just printed to the screen
407 .  number - the generic error number
408 .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
409 -  ctx - error handler context
410 
411    Options Database Keys:
412 .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
413    debugger attachment
414 
415    Level: developer
416 
417    Notes:
418    By default the GNU debugger, gdb, is used.  Alternatives are lldb, dbx and
419    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
420 
421    Most users need not directly employ this routine and the other error
422    handlers, but can instead use the simplified interface SETERR, which has
423    the calling sequence
424 $     SETERRQ(PETSC_COMM_SELF,number,p,message)
425 
426    Notes for experienced users:
427    Use PetscPushErrorHandler() to set the desired error handler.  The
428    currently available PETSc error handlers are
429 $    PetscTraceBackErrorHandler()
430 $    PetscAttachDebuggerErrorHandler()
431 $    PetscAbortErrorHandler()
432    or you may write your own.
433 
434    Concepts: debugger^error handler
435    Concepts: error handler^attach debugger
436 
437 .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
438            PetscAbortErrorHandler()
439 @*/
440 PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
441 {
442   PetscErrorCode ierr;
443 
444   PetscFunctionBegin;
445   if (!fun) fun = "User provided function";
446   if (!mess) mess = " ";
447 
448   (*PetscErrorPrintf)("%s() line %d in %s %s\n",fun,line,file,mess);
449 
450   ierr = PetscAttachDebugger();
451   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
452   PetscFunctionReturn(0);
453 }
454 
455 /*@C
456    PetscStopForDebugger - Prints a message to the screen indicating how to
457          attach to the process with the debugger and then waits for the
458          debugger to attach.
459 
460    Not Collective
461 
462    Level: developer
463 
464    Notes: This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
465 
466    Developer Notes: Since this can be called by the error handler, should it be calling SETERRQ() and CHKERRQ()?
467 
468    Concepts: debugger^waiting for attachment
469 
470 .seealso: PetscSetDebugger(), PetscAttachDebugger()
471 @*/
472 PetscErrorCode  PetscStopForDebugger(void)
473 {
474   PetscErrorCode ierr;
475   PetscInt       sleeptime=0;
476 #if !defined(PETSC_CANNOT_START_DEBUGGER)
477   int            ppid;
478   PetscMPIInt    rank;
479   char           program[PETSC_MAX_PATH_LEN],hostname[256];
480   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
481 #endif
482 
483   PetscFunctionBegin;
484 #if defined(PETSC_CANNOT_START_DEBUGGER)
485   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
486 #else
487   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
488   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
489   ierr = PetscGetHostName(hostname,256);
490   if (ierr) {
491     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
492     PetscFunctionReturn(0);
493   }
494 
495   ierr = PetscGetProgramName(program,256);
496   if (ierr) {
497     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
498     PetscFunctionReturn(0);
499   }
500   if (!program[0]) {
501     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
502     PetscFunctionReturn(0);
503   }
504 
505   ppid = getpid();
506 
507   ierr = PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);CHKERRQ(ierr);
508   ierr = PetscStrcmp(PetscDebugger,"ddd",&isddd);CHKERRQ(ierr);
509   ierr = PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);CHKERRQ(ierr);
510   ierr = PetscStrcmp(PetscDebugger,"ups",&isups);CHKERRQ(ierr);
511   ierr = PetscStrcmp(PetscDebugger,"xldb",&isxldb);CHKERRQ(ierr);
512   ierr = PetscStrcmp(PetscDebugger,"xdb",&isxdb);CHKERRQ(ierr);
513   ierr = PetscStrcmp(PetscDebugger,"dbx",&isdbx);CHKERRQ(ierr);
514   ierr = PetscStrcmp(PetscDebugger,"lldb",&islldb);CHKERRQ(ierr);
515 
516   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
517   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
518   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
519   else if (isdbx) {
520 #if defined(PETSC_USE_P_FOR_DEBUGGER)
521      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
522 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
523      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
524 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
525      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
526 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
527      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
528 #else
529      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
530 #endif
531   }
532 #endif /* PETSC_CANNOT_START_DEBUGGER */
533 
534   fflush(stdout); /* ignore error because may already be in error handler */
535 
536   sleeptime = 25; /* default to sleep waiting for debugger */
537   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
538   if (sleeptime < 0) sleeptime = -sleeptime;
539 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
540   /*
541       HP cannot attach process to sleeping debugger, hence count instead
542   */
543   {
544     PetscReal x = 1.0;
545     int       i =10000000;
546     while (i--) x++;  /* cannot attach to sleeper */
547   }
548 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
549   /*
550       IBM sleep may return at anytime, hence must see if there is more time to sleep
551   */
552   {
553     int left = sleeptime;
554     while (left > 0) left = sleep(left) - 1;
555   }
556 #else
557   PetscSleep(sleeptime);
558 #endif
559   PetscFunctionReturn(0);
560 }
561 
562 
563 
564