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