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