xref: /petsc/src/sys/error/adebug.c (revision 2a2a294103554fc595c3f3b52979d3355e3de4bb)
1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay       Code to handle PETSc starting up in debuggers,etc.
3e5c89e4eSSatish Balay */
4e5c89e4eSSatish Balay 
5c6db04a5SJed Brown #include <petscsys.h>               /*I   "petscsys.h"   I*/
6e5c89e4eSSatish Balay #include <signal.h>
7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_UNISTD_H)
8e5c89e4eSSatish Balay #include <unistd.h>
9e5c89e4eSSatish Balay #endif
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay /*
12e5c89e4eSSatish Balay       These are the debugger and display used if the debugger is started up
13e5c89e4eSSatish Balay */
14b59f628eSBarry Smith static char      PetscDebugger[PETSC_MAX_PATH_LEN];
155e96ac45SJed Brown static char      DebugTerminal[PETSC_MAX_PATH_LEN];
16ace3abfcSBarry Smith static PetscBool Xterm = PETSC_TRUE;
17*2a2a2941SBarry Smith PetscBool        petscwaitonerror = PETSC_FALSE;
18e5c89e4eSSatish Balay 
195e96ac45SJed Brown /*@C
205e96ac45SJed Brown    PetscSetDebugTerminal - Sets the terminal to use (instead of xterm) for debugging.
215e96ac45SJed Brown 
225e96ac45SJed Brown    Not Collective
235e96ac45SJed Brown 
245e96ac45SJed Brown    Input Parameters:
25a2b725a8SWilliam Gropp .  terminal - name of terminal and any flags required to execute a program.
26a5ba6984SMatthew G. Knepley               For example "xterm -e", "urxvt -e", "gnome-terminal -x".
275e96ac45SJed Brown 
285e96ac45SJed Brown    Options Database Keys:
295e96ac45SJed Brown    -debug_terminal terminal - use this terminal instead of xterm
305e96ac45SJed Brown 
315e96ac45SJed Brown    Level: developer
325e96ac45SJed Brown 
335e96ac45SJed Brown    Notes:
345e96ac45SJed Brown    You can start the debugger for all processes in the same GNU screen session.
355e96ac45SJed Brown 
36a6404fbfSBarry Smith      mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
375e96ac45SJed Brown 
385e96ac45SJed Brown    will open 4 windows in the session named "debug".
395e96ac45SJed Brown 
405e96ac45SJed Brown    Fortran Note:
415e96ac45SJed Brown    This routine is not supported in Fortran.
425e96ac45SJed Brown 
435e96ac45SJed Brown .seealso: PetscSetDebugger()
445e96ac45SJed Brown @*/
457087cfbeSBarry Smith PetscErrorCode  PetscSetDebugTerminal(const char terminal[])
465e96ac45SJed Brown {
475e96ac45SJed Brown   PetscErrorCode ierr;
485e96ac45SJed Brown 
495e96ac45SJed Brown   PetscFunctionBegin;
50589a23caSBarry Smith   ierr = PetscStrncpy(DebugTerminal,terminal,sizeof(DebugTerminal));CHKERRQ(ierr);
515e96ac45SJed Brown   PetscFunctionReturn(0);
525e96ac45SJed Brown }
535e96ac45SJed Brown 
54e5c89e4eSSatish Balay /*@C
55e5c89e4eSSatish Balay    PetscSetDebugger - Sets options associated with the debugger.
56e5c89e4eSSatish Balay 
57e5c89e4eSSatish Balay    Not Collective
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay    Input Parameters:
60e5c89e4eSSatish Balay +  debugger - name of debugger, which should be in your path,
61c4fb7a8fSRichard Tran Mills               usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
62e5c89e4eSSatish Balay               supports "xdb", and IBM rs6000 supports "xldb".
63e5c89e4eSSatish Balay 
648d359177SBarry Smith -  xterm - flag to indicate debugger window, set to either PETSC_TRUE (to indicate
658d359177SBarry Smith             debugger should be started in a new xterm) or PETSC_FALSE (to start debugger
668d359177SBarry Smith             in initial window (the option PETSC_FALSE makes no sense when using more
678d359177SBarry Smith             than one MPI process.)
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay    Level: developer
70e5c89e4eSSatish Balay 
71e5c89e4eSSatish Balay    Fortran Note:
72e5c89e4eSSatish Balay    This routine is not supported in Fortran.
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler()
75e5c89e4eSSatish Balay @*/
767087cfbeSBarry Smith PetscErrorCode  PetscSetDebugger(const char debugger[],PetscBool xterm)
77e5c89e4eSSatish Balay {
78e5c89e4eSSatish Balay   PetscErrorCode ierr;
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay   PetscFunctionBegin;
81e5c89e4eSSatish Balay   if (debugger) {
82589a23caSBarry Smith     ierr = PetscStrncpy(PetscDebugger,debugger,sizeof(PetscDebugger));CHKERRQ(ierr);
83e5c89e4eSSatish Balay   }
84589a23caSBarry Smith   if (Xterm) Xterm = xterm;
85e5c89e4eSSatish Balay   PetscFunctionReturn(0);
86e5c89e4eSSatish Balay }
87e5c89e4eSSatish Balay 
888d359177SBarry Smith /*@C
89f35f84d1SBarry Smith     PetscSetDefaultDebugger - Causes PETSc to use its default  debugger.
90e5c89e4eSSatish Balay 
91e5c89e4eSSatish Balay    Not collective
92e5c89e4eSSatish Balay 
938d359177SBarry Smith     Level: developer
94e5c89e4eSSatish Balay 
95e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
96e5c89e4eSSatish Balay @*/
977087cfbeSBarry Smith PetscErrorCode  PetscSetDefaultDebugger(void)
98e5c89e4eSSatish Balay {
99e5c89e4eSSatish Balay   PetscErrorCode ierr;
100e5c89e4eSSatish Balay 
101e5c89e4eSSatish Balay   PetscFunctionBegin;
1024211eb48SBarry Smith #if defined(PETSC_USE_DEBUGGER)
1034211eb48SBarry Smith   ierr = PetscSetDebugger(PETSC_USE_DEBUGGER,PETSC_TRUE);CHKERRQ(ierr);
104e5c89e4eSSatish Balay #endif
1055e96ac45SJed Brown   ierr = PetscSetDebugTerminal("xterm -e");CHKERRQ(ierr);
106e5c89e4eSSatish Balay   PetscFunctionReturn(0);
107e5c89e4eSSatish Balay }
108e5c89e4eSSatish Balay 
109e5c89e4eSSatish Balay static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
110e5c89e4eSSatish Balay {
111ace3abfcSBarry Smith   PetscBool      exists;
112e5c89e4eSSatish Balay   char           *f;
113e5c89e4eSSatish Balay   PetscErrorCode ierr;
114e5c89e4eSSatish Balay 
115e5c89e4eSSatish Balay   PetscFunctionBegin;
116e5c89e4eSSatish Balay   ierr = PetscStrstr(string, defaultDbg, &f);CHKERRQ(ierr);
117e5c89e4eSSatish Balay   if (f) {
118e5c89e4eSSatish Balay     ierr = PetscTestFile(string, 'x', &exists);CHKERRQ(ierr);
119a297a907SKarl Rupp     if (exists) *debugger = string;
120a297a907SKarl Rupp     else        *debugger = defaultDbg;
121e5c89e4eSSatish Balay   }
122e5c89e4eSSatish Balay   PetscFunctionReturn(0);
123e5c89e4eSSatish Balay }
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay /*@C
126e5c89e4eSSatish Balay     PetscSetDebuggerFromString - Set the complete path for the
127e5c89e4eSSatish Balay        debugger for PETSc to use.
128e5c89e4eSSatish Balay 
129e5c89e4eSSatish Balay    Not collective
130e5c89e4eSSatish Balay 
1317c764164SBarry Smith    Level: developer
132e5c89e4eSSatish Balay 
133e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
134e5c89e4eSSatish Balay @*/
1357c764164SBarry Smith PetscErrorCode  PetscSetDebuggerFromString(const char *string)
136e5c89e4eSSatish Balay {
1370298fd71SBarry Smith   const char     *debugger = NULL;
138ace3abfcSBarry Smith   PetscBool      xterm     = PETSC_TRUE;
139e5c89e4eSSatish Balay   char           *f;
140e5c89e4eSSatish Balay   PetscErrorCode ierr;
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay   PetscFunctionBegin;
143e5c89e4eSSatish Balay   ierr = PetscStrstr(string, "noxterm", &f);CHKERRQ(ierr);
144e5c89e4eSSatish Balay   if (f) xterm = PETSC_FALSE;
145e5c89e4eSSatish Balay   ierr = PetscStrstr(string, "ddd", &f);CHKERRQ(ierr);
146e5c89e4eSSatish Balay   if (f) xterm = PETSC_FALSE;
147e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("xdb",      string, &debugger);CHKERRQ(ierr);
148e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("dbx",      string, &debugger);CHKERRQ(ierr);
149e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("xldb",     string, &debugger);CHKERRQ(ierr);
150e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("gdb",      string, &debugger);CHKERRQ(ierr);
151c4fb7a8fSRichard Tran Mills   ierr = PetscCheckDebugger_Private("cuda-gdb", string, &debugger);CHKERRQ(ierr);
152e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("idb",      string, &debugger);CHKERRQ(ierr);
153e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("xxgdb",    string, &debugger);CHKERRQ(ierr);
154e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("ddd",      string, &debugger);CHKERRQ(ierr);
155bf902449SSatish Balay   ierr = PetscCheckDebugger_Private("kdbg",     string, &debugger);CHKERRQ(ierr);
156e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("ups",      string, &debugger);CHKERRQ(ierr);
157e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("workshop", string, &debugger);CHKERRQ(ierr);
158e5c89e4eSSatish Balay   ierr = PetscCheckDebugger_Private("pgdbg",    string, &debugger);CHKERRQ(ierr);
159ecbcaa78SBarry Smith   ierr = PetscCheckDebugger_Private("pathdb",   string, &debugger);CHKERRQ(ierr);
1600e9bae81SBarry Smith   ierr = PetscCheckDebugger_Private("lldb",     string, &debugger);CHKERRQ(ierr);
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay   ierr = PetscSetDebugger(debugger, xterm);CHKERRQ(ierr);
163e5c89e4eSSatish Balay   PetscFunctionReturn(0);
164e5c89e4eSSatish Balay }
165e5c89e4eSSatish Balay 
166*2a2a2941SBarry Smith /*@
167*2a2a2941SBarry Smith    PetscWaitOnError - If an error is detected and the process would normally exit the main program with MPI_Abort() sleep instead
168*2a2a2941SBarry Smith                       of exiting.
169*2a2a2941SBarry Smith 
170*2a2a2941SBarry Smith    Not Collective
171*2a2a2941SBarry Smith 
172*2a2a2941SBarry Smith    Level: advanced
173*2a2a2941SBarry Smith 
174*2a2a2941SBarry Smith    Notes:
175*2a2a2941SBarry Smith       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
176*2a2a2941SBarry Smith       killing the user's debugging sessions.
177*2a2a2941SBarry Smith 
178*2a2a2941SBarry Smith 
179*2a2a2941SBarry Smith .seealso: PetscSetDebugger(), PetscAttachDebugger()
180*2a2a2941SBarry Smith @*/
181*2a2a2941SBarry Smith PetscErrorCode  PetscWaitOnError()
182*2a2a2941SBarry Smith {
183*2a2a2941SBarry Smith   petscwaitonerror  = PETSC_TRUE;
184*2a2a2941SBarry Smith   return 0;
185*2a2a2941SBarry Smith }
186e5c89e4eSSatish Balay 
187e30d2299SSatish Balay /*@
188e5c89e4eSSatish Balay    PetscAttachDebugger - Attaches the debugger to the running process.
189e5c89e4eSSatish Balay 
190e5c89e4eSSatish Balay    Not Collective
191e5c89e4eSSatish Balay 
192e5c89e4eSSatish Balay    Level: advanced
193e5c89e4eSSatish Balay 
19495452b02SPatrick Sanan    Developer Notes:
19595452b02SPatrick Sanan     Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?
196f35f84d1SBarry Smith 
197e5c89e4eSSatish Balay .seealso: PetscSetDebugger()
198e5c89e4eSSatish Balay @*/
1997087cfbeSBarry Smith PetscErrorCode  PetscAttachDebugger(void)
200e5c89e4eSSatish Balay {
201ed50d614Sprj- #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
202e5c89e4eSSatish Balay   int            child    =0;
203a6d0e24fSJed Brown   PetscReal      sleeptime=0;
204e5c89e4eSSatish Balay   PetscErrorCode ierr;
205e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
206e5c89e4eSSatish Balay #endif
207e5c89e4eSSatish Balay 
208e5c89e4eSSatish Balay   PetscFunctionBegin;
209e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
210e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger\n");
211e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
212e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
21341e02c4dSJunchao Zhang   PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_SUP_SYS);
214e5c89e4eSSatish Balay #else
215589a23caSBarry Smith   ierr = PetscGetDisplay(display,sizeof(display));CHKERRQ(ierr);
216589a23caSBarry Smith   ierr = PetscGetProgramName(program,sizeof(program));CHKERRQ(ierr);
217e5c89e4eSSatish Balay   if (ierr) {
218e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
219e5c89e4eSSatish Balay     PetscFunctionReturn(1);
220e5c89e4eSSatish Balay   }
221e5c89e4eSSatish Balay   if (!program[0]) {
222e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
223e5c89e4eSSatish Balay     PetscFunctionReturn(1);
224e5c89e4eSSatish Balay   }
225e5c89e4eSSatish Balay   child = (int)fork();
226e5c89e4eSSatish Balay   if (child < 0) {
227e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Error in fork() attaching debugger\n");
228e5c89e4eSSatish Balay     PetscFunctionReturn(1);
229e5c89e4eSSatish Balay   }
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay   /*
232e5c89e4eSSatish Balay       Swap role the parent and child. This is (I think) so that control c typed
233e5c89e4eSSatish Balay     in the debugger goes to the correct process.
234e5c89e4eSSatish Balay   */
235234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
236a297a907SKarl Rupp   if (child) child = 0;
237a297a907SKarl Rupp   else       child = (int)getppid();
238234acd79SBarry Smith #endif
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay   if (child) { /* I am the parent, will run the debugger */
241e5c89e4eSSatish Balay     const char *args[10];
242e5c89e4eSSatish Balay     char       pid[10];
2435e96ac45SJed Brown     PetscInt   j,jj;
2440e9bae81SBarry Smith     PetscBool  isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg,islldb;
245e5c89e4eSSatish Balay 
246589a23caSBarry Smith     ierr = PetscGetHostName(hostname,sizeof(hostname));CHKERRQ(ierr);
247e5c89e4eSSatish Balay     /*
248e5c89e4eSSatish Balay          We need to send a continue signal to the "child" process on the
249e5c89e4eSSatish Balay        alpha, otherwise it just stays off forever
250e5c89e4eSSatish Balay     */
251e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
252e5c89e4eSSatish Balay     kill(child,SIGCONT);
253e5c89e4eSSatish Balay #endif
254e5c89e4eSSatish Balay     sprintf(pid,"%d",child);
255e5c89e4eSSatish Balay 
256b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);CHKERRQ(ierr);
257b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"ddd",&isddd);CHKERRQ(ierr);
258b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);CHKERRQ(ierr);
259b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"ups",&isups);CHKERRQ(ierr);
260b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"xldb",&isxldb);CHKERRQ(ierr);
261b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"xdb",&isxdb);CHKERRQ(ierr);
262b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"dbx",&isdbx);CHKERRQ(ierr);
263b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"idb",&isidb);CHKERRQ(ierr);
264b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"workshop",&isworkshop);CHKERRQ(ierr);
265b59f628eSBarry Smith     ierr = PetscStrcmp(PetscDebugger,"lldb",&islldb);CHKERRQ(ierr);
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay     if (isxxgdb || isups || isddd) {
268e5c89e4eSSatish Balay       args[1] = program; args[2] = pid; args[3] = "-display";
26902c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[4] = display; args[5] = NULL;
270c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
271e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
272e5c89e4eSSatish Balay         perror("Unable to start debugger");
273e5c89e4eSSatish Balay         exit(0);
274e5c89e4eSSatish Balay       }
275bf902449SSatish Balay     } else if (iskdbg) {
276bf902449SSatish Balay       args[1] = "-p"; args[2] = pid; args[3] = program;  args[4] = "-display";
27702c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
278c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname);
279bf902449SSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
280bf902449SSatish Balay         perror("Unable to start debugger");
281bf902449SSatish Balay         exit(0);
282bf902449SSatish Balay       }
283e5c89e4eSSatish Balay     } else if (isxldb) {
284e5c89e4eSSatish Balay       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
28502c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
286c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
287e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
288e5c89e4eSSatish Balay         perror("Unable to start debugger");
289e5c89e4eSSatish Balay         exit(0);
290e5c89e4eSSatish Balay       }
291e5c89e4eSSatish Balay     } else if (isworkshop) {
292e5c89e4eSSatish Balay       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
29302c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = NULL;
294c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
295e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
296e5c89e4eSSatish Balay         perror("Unable to start debugger");
297e5c89e4eSSatish Balay         exit(0);
298e5c89e4eSSatish Balay       }
2995e96ac45SJed Brown     } else {
3005e96ac45SJed Brown       j = 0;
3015e96ac45SJed Brown       if (Xterm) {
302ace3abfcSBarry Smith         PetscBool cmp;
3035e96ac45SJed Brown         char      *tmp,*tmp1;
3045e96ac45SJed Brown         ierr = PetscStrncmp(DebugTerminal,"screen",6,&cmp);CHKERRQ(ierr);
305a5ba6984SMatthew G. Knepley         if (!cmp) {ierr = PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp);CHKERRQ(ierr);}
3065e96ac45SJed Brown         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3075e96ac45SJed Brown         args[j++] = tmp = DebugTerminal;
3085e96ac45SJed Brown         if (display[0]) {
3095e96ac45SJed Brown           args[j++] = "-display"; args[j++] = display;
3105e96ac45SJed Brown         }
3115e96ac45SJed Brown         while (*tmp) {
3125e96ac45SJed Brown           ierr = PetscStrchr(tmp,' ',&tmp1);CHKERRQ(ierr);
3135e96ac45SJed Brown           if (!tmp1) break;
3145e96ac45SJed Brown           *tmp1     = 0;
3155e96ac45SJed Brown           tmp       = tmp1+1;
3165e96ac45SJed Brown           args[j++] = tmp;
3175e96ac45SJed Brown         }
3185e96ac45SJed Brown       }
319b59f628eSBarry Smith       args[j++] = PetscDebugger;
3205e96ac45SJed Brown       jj = j;
32102c9f0b5SLisandro Dalcin       args[j++] = program; args[j++] = pid; args[j++] = NULL;
3225e96ac45SJed Brown 
323e5c89e4eSSatish Balay       if (isidb) {
3245e96ac45SJed Brown         j = jj;
3255e96ac45SJed Brown         args[j++] = "-pid";
3265e96ac45SJed Brown         args[j++] = pid;
3275e96ac45SJed Brown         args[j++] = "-gdb";
3285e96ac45SJed Brown         args[j++] = program;
32902c9f0b5SLisandro Dalcin         args[j++] = NULL;
330e5c89e4eSSatish Balay       }
3310e9bae81SBarry Smith       if (islldb) {
3320e9bae81SBarry Smith         j = jj;
3330e9bae81SBarry Smith         args[j++] = "-p";
3340e9bae81SBarry Smith         args[j++] = pid;
33502c9f0b5SLisandro Dalcin         args[j++] = NULL;
3360e9bae81SBarry Smith       }
337e5c89e4eSSatish Balay       if (isdbx) {
3385e96ac45SJed Brown         j = jj;
3398d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3405e96ac45SJed Brown         args[j++] = "-p";
3415e96ac45SJed Brown         args[j++] = pid;
3425e96ac45SJed Brown         args[j++] = program;
343e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
3445e96ac45SJed Brown         args[j++] = "-l";
3455e96ac45SJed Brown         args[j++] = "ALL";
3465e96ac45SJed Brown         args[j++] = "-P";
3475e96ac45SJed Brown         args[j++] = pid;
3485e96ac45SJed Brown         args[j++] = program;
349e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
3505e96ac45SJed Brown         args[j++] = "-a";
3515e96ac45SJed Brown         args[j++] = pid;
352e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
3535e96ac45SJed Brown         args[j++] = "-pid";
3545e96ac45SJed Brown         args[j++] = pid;
3555e96ac45SJed Brown         args[j++] = program;
356493de400SSatish Balay #else
357493de400SSatish Balay         args[j++] = program;
358493de400SSatish Balay         args[j++] = pid;
3598d359177SBarry Smith #endif
36002c9f0b5SLisandro Dalcin         args[j++] = NULL;
361e5c89e4eSSatish Balay       }
3625e96ac45SJed Brown       if (Xterm) {
363c5888dd7SBarry Smith         if (display[0]) printf("PETSC: Attaching %s to %s of pid %s on display %s on machine %s\n",PetscDebugger,program,pid,display,hostname);
364c5888dd7SBarry Smith         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
365a297a907SKarl Rupp 
3665e96ac45SJed Brown         if (execvp(args[0],(char**)args)  < 0) {
3675e96ac45SJed Brown           perror("Unable to start debugger in xterm");
3685e96ac45SJed Brown           exit(0);
3695e96ac45SJed Brown         }
3705e96ac45SJed Brown       } else {
371c5888dd7SBarry Smith         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
372e5c89e4eSSatish Balay         if (execvp(args[0],(char**)args)  < 0) {
373e5c89e4eSSatish Balay           perror("Unable to start debugger");
374e5c89e4eSSatish Balay           exit(0);
375e5c89e4eSSatish Balay         }
376e5c89e4eSSatish Balay       }
377e5c89e4eSSatish Balay     }
378e5c89e4eSSatish Balay   } else {   /* I am the child, continue with user code */
379e5c89e4eSSatish Balay     sleeptime = 10; /* default to sleep waiting for debugger */
380c5929fdfSBarry Smith     ierr = PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL);CHKERRQ(ierr);
381e5c89e4eSSatish Balay     if (sleeptime < 0) sleeptime = -sleeptime;
382e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
383e5c89e4eSSatish Balay     /*
384e5c89e4eSSatish Balay         HP cannot attach process to sleeping debugger, hence count instead
385e5c89e4eSSatish Balay     */
386e5c89e4eSSatish Balay     {
387e5c89e4eSSatish Balay       PetscReal x = 1.0;
388e5c89e4eSSatish Balay       int       i =10000000;
389e5c89e4eSSatish Balay       while (i--) x++;  /* cannot attach to sleeper */
390e5c89e4eSSatish Balay     }
391e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
392e5c89e4eSSatish Balay     /*
393e5c89e4eSSatish Balay         IBM sleep may return at anytime, hence must see if there is more time to sleep
394e5c89e4eSSatish Balay     */
395e5c89e4eSSatish Balay     {
396e5c89e4eSSatish Balay       int left = sleeptime;
397a297a907SKarl Rupp       while (left > 0) left = PetscSleep(left) - 1;
398e5c89e4eSSatish Balay     }
399e5c89e4eSSatish Balay #else
400e5c89e4eSSatish Balay     PetscSleep(sleeptime);
401e5c89e4eSSatish Balay #endif
402e5c89e4eSSatish Balay   }
403e5c89e4eSSatish Balay #endif
404e5c89e4eSSatish Balay   PetscFunctionReturn(0);
405e5c89e4eSSatish Balay }
406e5c89e4eSSatish Balay 
407e5c89e4eSSatish Balay /*@C
408e5c89e4eSSatish Balay    PetscAttachDebuggerErrorHandler - Error handler that attaches
409e5c89e4eSSatish Balay    a debugger to a running process when an error is detected.
410e5c89e4eSSatish Balay    This routine is useful for examining variables, etc.
411e5c89e4eSSatish Balay 
412e5c89e4eSSatish Balay    Not Collective
413e5c89e4eSSatish Balay 
414e5c89e4eSSatish Balay    Input Parameters:
415e32f2f54SBarry Smith +  comm - communicator over which error occurred
416e32f2f54SBarry Smith .  line - the line number of the error (indicated by __LINE__)
417e5c89e4eSSatish Balay .  file - the file in which the error was detected (indicated by __FILE__)
418e5c89e4eSSatish Balay .  message - an error text string, usually just printed to the screen
419e5c89e4eSSatish Balay .  number - the generic error number
420668f157eSBarry Smith .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
421e5c89e4eSSatish Balay -  ctx - error handler context
422e5c89e4eSSatish Balay 
423e5c89e4eSSatish Balay    Options Database Keys:
424e5c89e4eSSatish Balay .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates
425e5c89e4eSSatish Balay    debugger attachment
426e5c89e4eSSatish Balay 
427e5c89e4eSSatish Balay    Level: developer
428e5c89e4eSSatish Balay 
429e5c89e4eSSatish Balay    Notes:
430c4fb7a8fSRichard Tran Mills    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
431e5c89e4eSSatish Balay    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
432e5c89e4eSSatish Balay 
433e5c89e4eSSatish Balay    Most users need not directly employ this routine and the other error
434e5c89e4eSSatish Balay    handlers, but can instead use the simplified interface SETERR, which has
435e5c89e4eSSatish Balay    the calling sequence
436e32f2f54SBarry Smith $     SETERRQ(PETSC_COMM_SELF,number,p,message)
437e5c89e4eSSatish Balay 
438e5c89e4eSSatish Balay    Notes for experienced users:
439e5c89e4eSSatish Balay    Use PetscPushErrorHandler() to set the desired error handler.  The
440e5c89e4eSSatish Balay    currently available PETSc error handlers are
441e5c89e4eSSatish Balay $    PetscTraceBackErrorHandler()
442e5c89e4eSSatish Balay $    PetscAttachDebuggerErrorHandler()
443e5c89e4eSSatish Balay $    PetscAbortErrorHandler()
444e5c89e4eSSatish Balay    or you may write your own.
445e5c89e4eSSatish Balay 
446e5c89e4eSSatish Balay 
447e5c89e4eSSatish Balay .seealso:  PetscPushErrorHandler(), PetscTraceBackErrorHandler(),
448e5c89e4eSSatish Balay            PetscAbortErrorHandler()
449e5c89e4eSSatish Balay @*/
450efca3c55SSatish Balay PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
451e5c89e4eSSatish Balay {
452e5c89e4eSSatish Balay   PetscErrorCode ierr;
453e5c89e4eSSatish Balay 
454e5c89e4eSSatish Balay   PetscFunctionBegin;
455e5c89e4eSSatish Balay   if (!fun) fun = "User provided function";
456e5c89e4eSSatish Balay   if (!mess) mess = " ";
457e5c89e4eSSatish Balay 
458efca3c55SSatish Balay   (*PetscErrorPrintf)("%s() line %d in %s %s\n",fun,line,file,mess);
459e5c89e4eSSatish Balay 
460e5c89e4eSSatish Balay   ierr = PetscAttachDebugger();
461a297a907SKarl Rupp   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
462e5c89e4eSSatish Balay   PetscFunctionReturn(0);
463e5c89e4eSSatish Balay }
464e5c89e4eSSatish Balay 
465e5c89e4eSSatish Balay /*@C
466e5c89e4eSSatish Balay    PetscStopForDebugger - Prints a message to the screen indicating how to
467e5c89e4eSSatish Balay          attach to the process with the debugger and then waits for the
468e5c89e4eSSatish Balay          debugger to attach.
469e5c89e4eSSatish Balay 
470e5c89e4eSSatish Balay    Not Collective
471e5c89e4eSSatish Balay 
4728d359177SBarry Smith    Level: developer
473e5c89e4eSSatish Balay 
47495452b02SPatrick Sanan    Notes:
47595452b02SPatrick Sanan     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
4768d359177SBarry Smith 
47795452b02SPatrick Sanan    Developer Notes:
47895452b02SPatrick Sanan     Since this can be called by the error handler, should it be calling SETERRQ() and CHKERRQ()?
479f35f84d1SBarry Smith 
480e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscAttachDebugger()
481e5c89e4eSSatish Balay @*/
4827087cfbeSBarry Smith PetscErrorCode  PetscStopForDebugger(void)
483e5c89e4eSSatish Balay {
484e5c89e4eSSatish Balay   PetscErrorCode ierr;
485e5c89e4eSSatish Balay   PetscInt       sleeptime=0;
486e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
48751ec2c11SGlenn Hammond   int            ppid;
488e5c89e4eSSatish Balay   PetscMPIInt    rank;
489e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],hostname[256];
4908d359177SBarry Smith   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
491e5c89e4eSSatish Balay #endif
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   PetscFunctionBegin;
494e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
495e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
496e5c89e4eSSatish Balay #else
497e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
498f35f84d1SBarry Smith   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
499589a23caSBarry Smith   ierr = PetscGetHostName(hostname,sizeof(hostname));
500e5c89e4eSSatish Balay   if (ierr) {
501e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
502e5c89e4eSSatish Balay     PetscFunctionReturn(0);
503e5c89e4eSSatish Balay   }
504e5c89e4eSSatish Balay 
505589a23caSBarry Smith   ierr = PetscGetProgramName(program,sizeof(program));
506e5c89e4eSSatish Balay   if (ierr) {
507e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
508e5c89e4eSSatish Balay     PetscFunctionReturn(0);
509e5c89e4eSSatish Balay   }
510e5c89e4eSSatish Balay   if (!program[0]) {
511e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
512e5c89e4eSSatish Balay     PetscFunctionReturn(0);
513e5c89e4eSSatish Balay   }
514e5c89e4eSSatish Balay 
515e5c89e4eSSatish Balay   ppid = getpid();
516e5c89e4eSSatish Balay 
517b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb);CHKERRQ(ierr);
518b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"ddd",&isddd);CHKERRQ(ierr);
519b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"kdbg",&iskdbg);CHKERRQ(ierr);
520b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"ups",&isups);CHKERRQ(ierr);
521b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"xldb",&isxldb);CHKERRQ(ierr);
522b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"xdb",&isxdb);CHKERRQ(ierr);
523b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"dbx",&isdbx);CHKERRQ(ierr);
524b59f628eSBarry Smith   ierr = PetscStrcmp(PetscDebugger,"lldb",&islldb);CHKERRQ(ierr);
525e5c89e4eSSatish Balay 
526c5888dd7SBarry Smith   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
527c5888dd7SBarry Smith   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
528c5888dd7SBarry Smith   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
5298d359177SBarry Smith   else if (isdbx) {
530e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
531c5888dd7SBarry Smith      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
532e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
533c5888dd7SBarry Smith      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
534e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
535c5888dd7SBarry Smith      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
536e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
537c5888dd7SBarry Smith      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
538e5c89e4eSSatish Balay #else
539c5888dd7SBarry Smith      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
540e5c89e4eSSatish Balay #endif
5418d359177SBarry Smith   }
542e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
543e5c89e4eSSatish Balay 
544f35f84d1SBarry Smith   fflush(stdout); /* ignore error because may already be in error handler */
545e5c89e4eSSatish Balay 
546e5c89e4eSSatish Balay   sleeptime = 25; /* default to sleep waiting for debugger */
547c5929fdfSBarry Smith   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
548e5c89e4eSSatish Balay   if (sleeptime < 0) sleeptime = -sleeptime;
549e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
550e5c89e4eSSatish Balay   /*
551e5c89e4eSSatish Balay       HP cannot attach process to sleeping debugger, hence count instead
552e5c89e4eSSatish Balay   */
553e5c89e4eSSatish Balay   {
554e5c89e4eSSatish Balay     PetscReal x = 1.0;
555e5c89e4eSSatish Balay     int       i =10000000;
556e5c89e4eSSatish Balay     while (i--) x++;  /* cannot attach to sleeper */
557e5c89e4eSSatish Balay   }
558e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
559e5c89e4eSSatish Balay   /*
560e5c89e4eSSatish Balay       IBM sleep may return at anytime, hence must see if there is more time to sleep
561e5c89e4eSSatish Balay   */
562e5c89e4eSSatish Balay   {
563e5c89e4eSSatish Balay     int left = sleeptime;
564a297a907SKarl Rupp     while (left > 0) left = sleep(left) - 1;
565e5c89e4eSSatish Balay   }
566e5c89e4eSSatish Balay #else
567e5c89e4eSSatish Balay   PetscSleep(sleeptime);
568e5c89e4eSSatish Balay #endif
569e5c89e4eSSatish Balay   PetscFunctionReturn(0);
570e5c89e4eSSatish Balay }
571