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