xref: /petsc/src/sys/error/adebug.c (revision 8865f1ea4ea560cd84ab8db62e98b7095cdff96f)
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 
480   PetscFunctionReturn(0);
481 }
482 
483 #undef __FUNCT__
484 #define __FUNCT__ "PetscStopForDebugger"
485 /*@C
486    PetscStopForDebugger - Prints a message to the screen indicating how to
487          attach to the process with the debugger and then waits for the
488          debugger to attach.
489 
490    Not Collective
491 
492    Level: advanced
493 
494    Developer Notes: Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?
495 
496    Concepts: debugger^waiting for attachment
497 
498 .seealso: PetscSetDebugger(), PetscAttachDebugger()
499 @*/
500 PetscErrorCode  PetscStopForDebugger(void)
501 {
502   PetscErrorCode ierr;
503   PetscInt       sleeptime=0;
504 #if !defined(PETSC_CANNOT_START_DEBUGGER)
505   int            ppid;
506   PetscMPIInt    rank;
507   char           program[PETSC_MAX_PATH_LEN],hostname[256];
508   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb;
509 #endif
510 
511   PetscFunctionBegin;
512 #if defined(PETSC_CANNOT_START_DEBUGGER)
513   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
514 #else
515   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
516   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
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,"kdbg",&iskdbg);CHKERRQ(ierr);
538   ierr = PetscStrcmp(Debugger,"ups",&isups);CHKERRQ(ierr);
539   ierr = PetscStrcmp(Debugger,"xldb",&isxldb);CHKERRQ(ierr);
540   ierr = PetscStrcmp(Debugger,"xdb",&isxdb);CHKERRQ(ierr);
541   ierr = PetscStrcmp(Debugger,"dbx",&isdbx);CHKERRQ(ierr);
542 
543   if (isxxgdb || isups || isddd || iskdbg) (*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) (*PetscErrorPrintf)("{%d]%s>>%s -a %d %s\n",rank,hostname,Debugger,ppid,program);
547 #endif
548 #if defined(PETSC_USE_P_FOR_DEBUGGER)
549   else if (isdbx) (*PetscErrorPrintf)("[%d]%s>>%s -p %d %s\n",rank,hostname,Debugger,ppid,program);
550 #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
551   else if (isxdb) (*PetscErrorPrintf)("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,Debugger,ppid,program);
552 #elif defined(PETSC_USE_A_FOR_DEBUGGER)
553   else if (isdbx) (*PetscErrorPrintf)("[%d]%s>>%s -a %d\n",rank,hostname,Debugger,ppid);
554 #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
555   else if (isdbx) (*PetscErrorPrintf)("[%d]%s>>%s -pid %d %s\n",rank,hostname,Debugger,ppid,program);
556 #else
557   else (*PetscErrorPrintf)("[%d]%s>>%s %s %d\n",rank,hostname,Debugger,program,ppid);
558 #endif
559 #endif /* PETSC_CANNOT_START_DEBUGGER */
560 
561   fflush(stdout); /* ignore error because may already be in error handler */
562 
563   sleeptime = 25; /* default to sleep waiting for debugger */
564   PetscOptionsGetInt(PETSC_NULL,"-debugger_pause",&sleeptime,PETSC_NULL); /* ignore error because may already be in error handler */
565   if (sleeptime < 0) sleeptime = -sleeptime;
566 #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
567   /*
568       HP cannot attach process to sleeping debugger, hence count instead
569   */
570   {
571     PetscReal x = 1.0;
572     int       i =10000000;
573     while (i--) x++;  /* cannot attach to sleeper */
574   }
575 #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
576   /*
577       IBM sleep may return at anytime, hence must see if there is more time to sleep
578   */
579   {
580     int left = sleeptime;
581     while (left > 0) left = sleep(left) - 1;
582   }
583 #else
584   PetscSleep(sleeptime);
585 #endif
586   PetscFunctionReturn(0);
587 }
588 
589 
590 
591