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