xref: /petsc/src/sys/error/adebug.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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];
16c823fc1fSBarry Smith static PetscBool UseDebugTerminal = PETSC_TRUE;
17baae8e41SSatish Balay PetscBool        petscwaitonerrorflg = PETSC_FALSE;
18bf4d2887SBarry Smith PetscBool        petscindebugger  = PETSC_FALSE;
19e5c89e4eSSatish Balay 
205e96ac45SJed Brown /*@C
21c823fc1fSBarry Smith    PetscSetDebugTerminal - Sets the terminal to use for debugging.
225e96ac45SJed Brown 
235e96ac45SJed Brown    Not Collective
245e96ac45SJed Brown 
255e96ac45SJed Brown    Input Parameters:
26a2b725a8SWilliam Gropp .  terminal - name of terminal and any flags required to execute a program.
27c823fc1fSBarry Smith               For example xterm, "urxvt -e", "gnome-terminal -x".
28c823fc1fSBarry Smith               On Apple MacOS you can use Terminal (note the capital T)
295e96ac45SJed Brown 
305e96ac45SJed Brown    Options Database Keys:
31c823fc1fSBarry Smith    -debug_terminal terminal - use this terminal instead of the default
325e96ac45SJed Brown 
335e96ac45SJed Brown    Level: developer
345e96ac45SJed Brown 
355e96ac45SJed Brown    Notes:
365e96ac45SJed Brown    You can start the debugger for all processes in the same GNU screen session.
375e96ac45SJed Brown 
38a6404fbfSBarry Smith      mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
395e96ac45SJed Brown 
405e96ac45SJed Brown    will open 4 windows in the session named "debug".
415e96ac45SJed Brown 
42c823fc1fSBarry Smith    The default on Apple is Terminal, on other systems the default is xterm
43c823fc1fSBarry Smith 
445e96ac45SJed Brown    Fortran Note:
455e96ac45SJed Brown    This routine is not supported in Fortran.
465e96ac45SJed Brown 
475e96ac45SJed Brown .seealso: PetscSetDebugger()
485e96ac45SJed Brown @*/
497087cfbeSBarry Smith PetscErrorCode PetscSetDebugTerminal(const char terminal[])
505e96ac45SJed Brown {
51c823fc1fSBarry Smith   PetscBool xterm;
525e96ac45SJed Brown 
535e96ac45SJed Brown   PetscFunctionBegin;
54*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrncpy(DebugTerminal,terminal,sizeof(DebugTerminal)));
55*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(terminal,"xterm",&xterm));
56*5f80ce2aSJacob Faibussowitsch   if (xterm) CHKERRQ(PetscStrlcat(DebugTerminal," -e",sizeof(DebugTerminal)));
575e96ac45SJed Brown   PetscFunctionReturn(0);
585e96ac45SJed Brown }
595e96ac45SJed Brown 
60e5c89e4eSSatish Balay /*@C
61e5c89e4eSSatish Balay    PetscSetDebugger - Sets options associated with the debugger.
62e5c89e4eSSatish Balay 
63e5c89e4eSSatish Balay    Not Collective
64e5c89e4eSSatish Balay 
65e5c89e4eSSatish Balay    Input Parameters:
66e5c89e4eSSatish Balay +  debugger - name of debugger, which should be in your path,
67c4fb7a8fSRichard Tran Mills               usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
68e5c89e4eSSatish Balay               supports "xdb", and IBM rs6000 supports "xldb".
69e5c89e4eSSatish Balay 
70c823fc1fSBarry Smith -  usedebugterminal - flag to indicate debugger window, set to either PETSC_TRUE (to indicate
71c823fc1fSBarry Smith             debugger should be started in a new terminal window) or PETSC_FALSE (to start debugger
728d359177SBarry Smith             in initial window (the option PETSC_FALSE makes no sense when using more
738d359177SBarry Smith             than one MPI process.)
74e5c89e4eSSatish Balay 
75e5c89e4eSSatish Balay    Level: developer
76e5c89e4eSSatish Balay 
77e5c89e4eSSatish Balay    Fortran Note:
78e5c89e4eSSatish Balay    This routine is not supported in Fortran.
79e5c89e4eSSatish Balay 
80c823fc1fSBarry Smith .seealso: PetscAttachDebugger(), PetscAttachDebuggerErrorHandler(), PetscSetDebugTerminal()
81e5c89e4eSSatish Balay @*/
82c823fc1fSBarry Smith PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
83e5c89e4eSSatish Balay {
84e5c89e4eSSatish Balay   PetscFunctionBegin;
85*5f80ce2aSJacob Faibussowitsch   if (debugger) CHKERRQ(PetscStrncpy(PetscDebugger,debugger,sizeof(PetscDebugger)));
86c823fc1fSBarry Smith   if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
87e5c89e4eSSatish Balay   PetscFunctionReturn(0);
88e5c89e4eSSatish Balay }
89e5c89e4eSSatish Balay 
908d359177SBarry Smith /*@C
91c823fc1fSBarry Smith     PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
92e5c89e4eSSatish Balay 
93e5c89e4eSSatish Balay    Not collective
94e5c89e4eSSatish Balay 
958d359177SBarry Smith     Level: developer
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscSetDebuggerFromString()
98e5c89e4eSSatish Balay @*/
997087cfbeSBarry Smith PetscErrorCode PetscSetDefaultDebugger(void)
100e5c89e4eSSatish Balay {
101e5c89e4eSSatish Balay   PetscFunctionBegin;
1024211eb48SBarry Smith #if defined(PETSC_USE_DEBUGGER)
103*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSetDebugger(PETSC_USE_DEBUGGER,PETSC_TRUE));
104e5c89e4eSSatish Balay #endif
105c823fc1fSBarry Smith #if defined(__APPLE__)
106*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSetDebugTerminal("Terminal"));
107c823fc1fSBarry Smith #else
108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSetDebugTerminal("xterm"));
109c823fc1fSBarry Smith #endif
110e5c89e4eSSatish Balay   PetscFunctionReturn(0);
111e5c89e4eSSatish Balay }
112e5c89e4eSSatish Balay 
113e5c89e4eSSatish Balay static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
114e5c89e4eSSatish Balay {
115ace3abfcSBarry Smith   PetscBool  exists;
116e5c89e4eSSatish Balay   char      *f;
117e5c89e4eSSatish Balay 
118e5c89e4eSSatish Balay   PetscFunctionBegin;
119*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrstr(string, defaultDbg, &f));
120e5c89e4eSSatish Balay   if (f) {
121*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTestFile(string, 'x', &exists));
122a297a907SKarl Rupp     if (exists) *debugger = string;
123a297a907SKarl Rupp     else        *debugger = defaultDbg;
124e5c89e4eSSatish Balay   }
125e5c89e4eSSatish Balay   PetscFunctionReturn(0);
126e5c89e4eSSatish Balay }
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay /*@C
129e5c89e4eSSatish Balay     PetscSetDebuggerFromString - Set the complete path for the
130e5c89e4eSSatish Balay        debugger for PETSc to use.
131e5c89e4eSSatish Balay 
132e5c89e4eSSatish Balay    Not collective
133e5c89e4eSSatish Balay 
1347c764164SBarry Smith    Level: developer
135e5c89e4eSSatish Balay 
136e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscSetDefaultDebugger()
137e5c89e4eSSatish Balay @*/
1387c764164SBarry Smith PetscErrorCode  PetscSetDebuggerFromString(const char *string)
139e5c89e4eSSatish Balay {
1400298fd71SBarry Smith   const char *debugger    = NULL;
141c823fc1fSBarry Smith   PetscBool   useterminal = PETSC_TRUE;
142e5c89e4eSSatish Balay   char       *f;
143e5c89e4eSSatish Balay 
144e5c89e4eSSatish Balay   PetscFunctionBegin;
145*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrstr(string, "noxterm", &f));
146c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
147*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrstr(string, "ddd", &f));
148c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
149*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrstr(string, "noterminal", &f));
150c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
151*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("xdb",      string, &debugger));
152*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("dbx",      string, &debugger));
153*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("xldb",     string, &debugger));
154*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("gdb",      string, &debugger));
155*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
156*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("idb",      string, &debugger));
157*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("xxgdb",    string, &debugger));
158*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("ddd",      string, &debugger));
159*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("kdbg",     string, &debugger));
160*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("ups",      string, &debugger));
161*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("workshop", string, &debugger));
162*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("pgdbg",    string, &debugger));
163*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("pathdb",   string, &debugger));
164*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCheckDebugger_Private("lldb",     string, &debugger));
165*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSetDebugger(debugger, useterminal));
166e5c89e4eSSatish Balay   PetscFunctionReturn(0);
167e5c89e4eSSatish Balay }
168e5c89e4eSSatish Balay 
1692a2a2941SBarry Smith /*@
1702a2a2941SBarry Smith    PetscWaitOnError - If an error is detected and the process would normally exit the main program with MPI_Abort() sleep instead
1712a2a2941SBarry Smith                       of exiting.
1722a2a2941SBarry Smith 
1732a2a2941SBarry Smith    Not Collective
1742a2a2941SBarry Smith 
1752a2a2941SBarry Smith    Level: advanced
1762a2a2941SBarry Smith 
1772a2a2941SBarry Smith    Notes:
1782a2a2941SBarry 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
1792a2a2941SBarry Smith       killing the user's debugging sessions.
1802a2a2941SBarry Smith 
1812a2a2941SBarry Smith .seealso: PetscSetDebugger(), PetscAttachDebugger()
1822a2a2941SBarry Smith @*/
1832a2a2941SBarry Smith PetscErrorCode  PetscWaitOnError()
1842a2a2941SBarry Smith {
185baae8e41SSatish Balay   petscwaitonerrorflg  = PETSC_TRUE;
1862a2a2941SBarry Smith   return 0;
1872a2a2941SBarry Smith }
188e5c89e4eSSatish Balay 
189e30d2299SSatish Balay /*@
190e5c89e4eSSatish Balay    PetscAttachDebugger - Attaches the debugger to the running process.
191e5c89e4eSSatish Balay 
192e5c89e4eSSatish Balay    Not Collective
193e5c89e4eSSatish Balay 
1941f690a00SBarry Smith    Options Database Keys:
1951f690a00SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] -debug_terminal xterm or Terminal (for Apple)
1961f690a00SBarry Smith .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
1971f690a00SBarry Smith 
198e5c89e4eSSatish Balay    Level: advanced
199e5c89e4eSSatish Balay 
20095452b02SPatrick Sanan    Developer Notes:
20195452b02SPatrick Sanan     Since this can be called by the error handler should it be calling SETERRQ() and CHKERRQ()?
202f35f84d1SBarry Smith 
2031f690a00SBarry Smith .seealso: PetscSetDebugger(), PetscSetDefaultDebugger(), PetscSetDebugTerminal(), PetscAttachDebuggerErrorHandler(), PetscStopForDebugger()
204e5c89e4eSSatish Balay @*/
2057087cfbeSBarry Smith PetscErrorCode PetscAttachDebugger(void)
206e5c89e4eSSatish Balay {
207ed50d614Sprj- #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
208e5c89e4eSSatish Balay   int            child    =0;
209a6d0e24fSJed Brown   PetscReal      sleeptime=0;
210e5c89e4eSSatish Balay   PetscErrorCode ierr;
211e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
212e5c89e4eSSatish Balay #endif
213e5c89e4eSSatish Balay 
214e5c89e4eSSatish Balay   PetscFunctionBegin;
215e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
216e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger\n");
217e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
218e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
21941e02c4dSJunchao Zhang   PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_SUP_SYS);
220e5c89e4eSSatish Balay #else
221*5f80ce2aSJacob Faibussowitsch   ierr = PetscGetDisplay(display,sizeof(display));
222*5f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(ierr)) {
223*5f80ce2aSJacob Faibussowitsch     (*PetscErrorPrintf)("Cannot determine display\n");
224*5f80ce2aSJacob Faibussowitsch     PetscFunctionReturn(PETSC_ERR_SYS);
225*5f80ce2aSJacob Faibussowitsch   }
226*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscGetProgramName(program,sizeof(program)));
227*5f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(ierr)) {
228e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
229a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
230e5c89e4eSSatish Balay   }
231*5f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(!program[0])) {
232e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
233a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
234e5c89e4eSSatish Balay   }
235e5c89e4eSSatish Balay   child = (int)fork();
236*5f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(child < 0)) {
237a995a477SBarry Smith     (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
238a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
239e5c89e4eSSatish Balay   }
240bf4d2887SBarry Smith   petscindebugger = PETSC_TRUE;
241e5c89e4eSSatish Balay 
242e5c89e4eSSatish Balay   /*
243e5c89e4eSSatish Balay       Swap role the parent and child. This is (I think) so that control c typed
244e5c89e4eSSatish Balay     in the debugger goes to the correct process.
245e5c89e4eSSatish Balay   */
246234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
247a297a907SKarl Rupp   if (child) child = 0;
248a297a907SKarl Rupp   else       child = (int)getppid();
249234acd79SBarry Smith #endif
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay   if (child) { /* I am the parent, will run the debugger */
252e5c89e4eSSatish Balay     const char *args[10];
253e5c89e4eSSatish Balay     char       pid[10];
2545e96ac45SJed Brown     PetscInt   j,jj;
2550e9bae81SBarry Smith     PetscBool  isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg,islldb;
256e5c89e4eSSatish Balay 
257*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscGetHostName(hostname,sizeof(hostname)));
258e5c89e4eSSatish Balay     /*
259e5c89e4eSSatish Balay          We need to send a continue signal to the "child" process on the
260e5c89e4eSSatish Balay        alpha, otherwise it just stays off forever
261e5c89e4eSSatish Balay     */
262e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
263e5c89e4eSSatish Balay     kill(child,SIGCONT);
264e5c89e4eSSatish Balay #endif
265e5c89e4eSSatish Balay     sprintf(pid,"%d",child);
266e5c89e4eSSatish Balay 
267*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
268*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"ddd",&isddd));
269*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
270*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"ups",&isups));
271*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
272*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
273*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
274*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"idb",&isidb));
275*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"workshop",&isworkshop));
276*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(PetscDebugger,"lldb",&islldb));
277e5c89e4eSSatish Balay 
278e5c89e4eSSatish Balay     if (isxxgdb || isups || isddd) {
279e5c89e4eSSatish Balay       args[1] = program; args[2] = pid; args[3] = "-display";
28002c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[4] = display; args[5] = NULL;
281c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
282e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
283e5c89e4eSSatish Balay         perror("Unable to start debugger");
284e5c89e4eSSatish Balay         exit(0);
285e5c89e4eSSatish Balay       }
286bf902449SSatish Balay     } else if (iskdbg) {
287bf902449SSatish Balay       args[1] = "-p"; args[2] = pid; args[3] = program;  args[4] = "-display";
28802c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
289c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname);
290bf902449SSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
291bf902449SSatish Balay         perror("Unable to start debugger");
292bf902449SSatish Balay         exit(0);
293bf902449SSatish Balay       }
294e5c89e4eSSatish Balay     } else if (isxldb) {
295e5c89e4eSSatish Balay       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
29602c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
297c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
298e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
299e5c89e4eSSatish Balay         perror("Unable to start debugger");
300e5c89e4eSSatish Balay         exit(0);
301e5c89e4eSSatish Balay       }
302e5c89e4eSSatish Balay     } else if (isworkshop) {
303e5c89e4eSSatish Balay       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
30402c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = NULL;
305c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
306e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
307e5c89e4eSSatish Balay         perror("Unable to start debugger");
308e5c89e4eSSatish Balay         exit(0);
309e5c89e4eSSatish Balay       }
3105e96ac45SJed Brown     } else {
3115e96ac45SJed Brown       j = 0;
312c823fc1fSBarry Smith       if (UseDebugTerminal) {
313ace3abfcSBarry Smith         PetscBool cmp;
3145e96ac45SJed Brown         char      *tmp,*tmp1;
315*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrncmp(DebugTerminal,"Terminal",8,&cmp));
316c823fc1fSBarry Smith         if (cmp) {
317c823fc1fSBarry Smith           char command[1024];
318*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSNPrintf(command,sizeof(command),"osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s  %s \"'\n",pid,program));
319*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",NULL));
320c823fc1fSBarry Smith           exit(0);
321c823fc1fSBarry Smith         }
322c823fc1fSBarry Smith 
323*5f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscStrncmp(DebugTerminal,"screen",6,&cmp));
324*5f80ce2aSJacob Faibussowitsch         if (!cmp) CHKERRQ(PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp));
3255e96ac45SJed Brown         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3265e96ac45SJed Brown         args[j++] = tmp = DebugTerminal;
3275e96ac45SJed Brown         if (display[0]) {
3285e96ac45SJed Brown           args[j++] = "-display"; args[j++] = display;
3295e96ac45SJed Brown         }
3305e96ac45SJed Brown         while (*tmp) {
331*5f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscStrchr(tmp,' ',&tmp1));
3325e96ac45SJed Brown           if (!tmp1) break;
3335e96ac45SJed Brown           *tmp1     = 0;
3345e96ac45SJed Brown           tmp       = tmp1+1;
3355e96ac45SJed Brown           args[j++] = tmp;
3365e96ac45SJed Brown         }
3375e96ac45SJed Brown       }
338b59f628eSBarry Smith       args[j++] = PetscDebugger;
3395e96ac45SJed Brown       jj = j;
340bf4d2887SBarry Smith       /* this is for default gdb */
341bf4d2887SBarry Smith       args[j++] = program;
342bf4d2887SBarry Smith       args[j++] = pid;
343bf4d2887SBarry Smith       args[j++] = NULL;
3445e96ac45SJed Brown 
345e5c89e4eSSatish Balay       if (isidb) {
3465e96ac45SJed Brown         j = jj;
3475e96ac45SJed Brown         args[j++] = "-pid";
3485e96ac45SJed Brown         args[j++] = pid;
3495e96ac45SJed Brown         args[j++] = "-gdb";
3505e96ac45SJed Brown         args[j++] = program;
35102c9f0b5SLisandro Dalcin         args[j++] = NULL;
352e5c89e4eSSatish Balay       }
3530e9bae81SBarry Smith       if (islldb) {
3540e9bae81SBarry Smith         j = jj;
3550e9bae81SBarry Smith         args[j++] = "-p";
3560e9bae81SBarry Smith         args[j++] = pid;
35702c9f0b5SLisandro Dalcin         args[j++] = NULL;
3580e9bae81SBarry Smith       }
359e5c89e4eSSatish Balay       if (isdbx) {
3605e96ac45SJed Brown         j = jj;
3618d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3625e96ac45SJed Brown         args[j++] = "-p";
3635e96ac45SJed Brown         args[j++] = pid;
3645e96ac45SJed Brown         args[j++] = program;
365e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
3665e96ac45SJed Brown         args[j++] = "-l";
3675e96ac45SJed Brown         args[j++] = "ALL";
3685e96ac45SJed Brown         args[j++] = "-P";
3695e96ac45SJed Brown         args[j++] = pid;
3705e96ac45SJed Brown         args[j++] = program;
371e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
3725e96ac45SJed Brown         args[j++] = "-a";
3735e96ac45SJed Brown         args[j++] = pid;
374e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
3755e96ac45SJed Brown         args[j++] = "-pid";
3765e96ac45SJed Brown         args[j++] = pid;
3775e96ac45SJed Brown         args[j++] = program;
378493de400SSatish Balay #else
379493de400SSatish Balay         args[j++] = program;
380493de400SSatish Balay         args[j++] = pid;
3818d359177SBarry Smith #endif
38202c9f0b5SLisandro Dalcin         args[j++] = NULL;
383e5c89e4eSSatish Balay       }
384c823fc1fSBarry Smith       if (UseDebugTerminal) {
385c5888dd7SBarry 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);
386c5888dd7SBarry Smith         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
387a297a907SKarl Rupp 
3885e96ac45SJed Brown         if (execvp(args[0],(char**)args)  < 0) {
3895e96ac45SJed Brown           perror("Unable to start debugger in xterm");
3905e96ac45SJed Brown           exit(0);
3915e96ac45SJed Brown         }
3925e96ac45SJed Brown       } else {
393c5888dd7SBarry Smith         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
394e5c89e4eSSatish Balay         if (execvp(args[0],(char**)args)  < 0) {
395e5c89e4eSSatish Balay           perror("Unable to start debugger");
396e5c89e4eSSatish Balay           exit(0);
397e5c89e4eSSatish Balay         }
398e5c89e4eSSatish Balay       }
399e5c89e4eSSatish Balay     }
400e5c89e4eSSatish Balay   } else {   /* I am the child, continue with user code */
401e5c89e4eSSatish Balay     sleeptime = 10; /* default to sleep waiting for debugger */
402*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL));
403e5c89e4eSSatish Balay     if (sleeptime < 0) sleeptime = -sleeptime;
404e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
405e5c89e4eSSatish Balay     /*
406e5c89e4eSSatish Balay         HP cannot attach process to sleeping debugger, hence count instead
407e5c89e4eSSatish Balay     */
408e5c89e4eSSatish Balay     {
409e5c89e4eSSatish Balay       PetscReal x = 1.0;
410e5c89e4eSSatish Balay       int       i =10000000;
411e5c89e4eSSatish Balay       while (i--) x++;  /* cannot attach to sleeper */
412e5c89e4eSSatish Balay     }
413e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
414e5c89e4eSSatish Balay     /*
415e5c89e4eSSatish Balay         IBM sleep may return at anytime, hence must see if there is more time to sleep
416e5c89e4eSSatish Balay     */
417e5c89e4eSSatish Balay     {
418e5c89e4eSSatish Balay       int left = sleeptime;
419a297a907SKarl Rupp       while (left > 0) left = PetscSleep(left) - 1;
420e5c89e4eSSatish Balay     }
421e5c89e4eSSatish Balay #else
422e5c89e4eSSatish Balay     PetscSleep(sleeptime);
423e5c89e4eSSatish Balay #endif
424e5c89e4eSSatish Balay   }
425e5c89e4eSSatish Balay #endif
426e5c89e4eSSatish Balay   PetscFunctionReturn(0);
427e5c89e4eSSatish Balay }
428e5c89e4eSSatish Balay 
429e5c89e4eSSatish Balay /*@C
430e5c89e4eSSatish Balay    PetscAttachDebuggerErrorHandler - Error handler that attaches
431e5c89e4eSSatish Balay    a debugger to a running process when an error is detected.
432e5c89e4eSSatish Balay    This routine is useful for examining variables, etc.
433e5c89e4eSSatish Balay 
434e5c89e4eSSatish Balay    Not Collective
435e5c89e4eSSatish Balay 
436e5c89e4eSSatish Balay    Input Parameters:
437e32f2f54SBarry Smith +  comm - communicator over which error occurred
438e32f2f54SBarry Smith .  line - the line number of the error (indicated by __LINE__)
439e5c89e4eSSatish Balay .  file - the file in which the error was detected (indicated by __FILE__)
440e5c89e4eSSatish Balay .  message - an error text string, usually just printed to the screen
441e5c89e4eSSatish Balay .  number - the generic error number
442668f157eSBarry Smith .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
443e5c89e4eSSatish Balay -  ctx - error handler context
444e5c89e4eSSatish Balay 
445e5c89e4eSSatish Balay    Options Database Keys:
44645b666d6SBarry Smith +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
44745b666d6SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
448e5c89e4eSSatish Balay 
449e5c89e4eSSatish Balay    Level: developer
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay    Notes:
452c4fb7a8fSRichard Tran Mills    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
453e5c89e4eSSatish Balay    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
454e5c89e4eSSatish Balay 
455e5c89e4eSSatish Balay    Most users need not directly employ this routine and the other error
456e5c89e4eSSatish Balay    handlers, but can instead use the simplified interface SETERR, which has
457e5c89e4eSSatish Balay    the calling sequence
458e32f2f54SBarry Smith $     SETERRQ(PETSC_COMM_SELF,number,p,message)
459e5c89e4eSSatish Balay 
460e5c89e4eSSatish Balay    Notes for experienced users:
461e5c89e4eSSatish Balay    Use PetscPushErrorHandler() to set the desired error handler.  The
462e5c89e4eSSatish Balay    currently available PETSc error handlers are
463e5c89e4eSSatish Balay $    PetscTraceBackErrorHandler()
464e5c89e4eSSatish Balay $    PetscAttachDebuggerErrorHandler()
465e5c89e4eSSatish Balay $    PetscAbortErrorHandler()
466e5c89e4eSSatish Balay    or you may write your own.
467e5c89e4eSSatish Balay 
46845b666d6SBarry Smith .seealso:  PetscSetDebuggerFromString(), PetscSetDebugger(), PetscSetDefaultDebugger(), PetscError(), PetscPushErrorHandler(), PetscPopErrorHandler(), PetscTraceBackErrorHandler(),
469c823fc1fSBarry Smith            PetscAbortErrorHandler(), PetscMPIAbortErrorHandler(), PetscEmacsClientErrorHandler(), PetscReturnErrorHandler(), PetscSetDebugTermainal()
470e5c89e4eSSatish Balay @*/
471efca3c55SSatish Balay PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
472e5c89e4eSSatish Balay {
473e5c89e4eSSatish Balay   PetscErrorCode ierr;
474e5c89e4eSSatish Balay 
475e5c89e4eSSatish Balay   PetscFunctionBegin;
476e5c89e4eSSatish Balay   if (!fun) fun = "User provided function";
477e5c89e4eSSatish Balay   if (!mess) mess = " ";
478e5c89e4eSSatish Balay 
4792f307e7aSJunchao Zhang   (*PetscErrorPrintf)("%s() at %s:%d %s\n",fun,file,line,mess);
480e5c89e4eSSatish Balay 
481e5c89e4eSSatish Balay   ierr = PetscAttachDebugger();
482a297a907SKarl Rupp   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
483e5c89e4eSSatish Balay   PetscFunctionReturn(0);
484e5c89e4eSSatish Balay }
485e5c89e4eSSatish Balay 
486e5c89e4eSSatish Balay /*@C
487e5c89e4eSSatish Balay    PetscStopForDebugger - Prints a message to the screen indicating how to
488e5c89e4eSSatish Balay          attach to the process with the debugger and then waits for the
489e5c89e4eSSatish Balay          debugger to attach.
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay    Not Collective
492e5c89e4eSSatish Balay 
4931f690a00SBarry Smith    Options Database:
4941f690a00SBarry Smith .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
4951f690a00SBarry Smith 
4968d359177SBarry Smith    Level: developer
497e5c89e4eSSatish Balay 
49895452b02SPatrick Sanan    Notes:
49995452b02SPatrick Sanan     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
5008d359177SBarry Smith 
50195452b02SPatrick Sanan    Developer Notes:
50295452b02SPatrick Sanan     Since this can be called by the error handler, should it be calling SETERRQ() and CHKERRQ()?
503f35f84d1SBarry Smith 
504e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscAttachDebugger()
505e5c89e4eSSatish Balay @*/
5067087cfbeSBarry Smith PetscErrorCode  PetscStopForDebugger(void)
507e5c89e4eSSatish Balay {
508e5c89e4eSSatish Balay   PetscErrorCode ierr;
509e5c89e4eSSatish Balay   PetscInt       sleeptime=0;
510e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
51151ec2c11SGlenn Hammond   int            ppid;
512e5c89e4eSSatish Balay   PetscMPIInt    rank;
513e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],hostname[256];
5148d359177SBarry Smith   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
515e5c89e4eSSatish Balay #endif
516e5c89e4eSSatish Balay 
517e5c89e4eSSatish Balay   PetscFunctionBegin;
518e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
519e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
520e5c89e4eSSatish Balay #else
521e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
522f35f84d1SBarry Smith   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
523589a23caSBarry Smith   ierr = PetscGetHostName(hostname,sizeof(hostname));
524e5c89e4eSSatish Balay   if (ierr) {
525e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
526e5c89e4eSSatish Balay     PetscFunctionReturn(0);
527e5c89e4eSSatish Balay   }
528e5c89e4eSSatish Balay 
529589a23caSBarry Smith   ierr = PetscGetProgramName(program,sizeof(program));
530e5c89e4eSSatish Balay   if (ierr) {
531e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
532e5c89e4eSSatish Balay     PetscFunctionReturn(0);
533e5c89e4eSSatish Balay   }
534e5c89e4eSSatish Balay   if (!program[0]) {
535e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
536e5c89e4eSSatish Balay     PetscFunctionReturn(0);
537e5c89e4eSSatish Balay   }
538e5c89e4eSSatish Balay 
539e5c89e4eSSatish Balay   ppid = getpid();
540e5c89e4eSSatish Balay 
541*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
542*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"ddd",&isddd));
543*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
544*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"ups",&isups));
545*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
546*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
547*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
548*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(PetscDebugger,"lldb",&islldb));
549e5c89e4eSSatish Balay 
550c5888dd7SBarry Smith   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
551c5888dd7SBarry Smith   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
552c5888dd7SBarry Smith   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
5538d359177SBarry Smith   else if (isdbx) {
554e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
555c5888dd7SBarry Smith      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
556e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
557c5888dd7SBarry Smith      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
558e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
559c5888dd7SBarry Smith      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
560e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
561c5888dd7SBarry Smith      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
562e5c89e4eSSatish Balay #else
563c5888dd7SBarry Smith      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
564e5c89e4eSSatish Balay #endif
5658d359177SBarry Smith   }
566e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
567e5c89e4eSSatish Balay 
568f35f84d1SBarry Smith   fflush(stdout); /* ignore error because may already be in error handler */
569e5c89e4eSSatish Balay 
570e5c89e4eSSatish Balay   sleeptime = 25; /* default to sleep waiting for debugger */
571c5929fdfSBarry Smith   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
572e5c89e4eSSatish Balay   if (sleeptime < 0) sleeptime = -sleeptime;
573e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
574e5c89e4eSSatish Balay   /*
575e5c89e4eSSatish Balay       HP cannot attach process to sleeping debugger, hence count instead
576e5c89e4eSSatish Balay   */
577e5c89e4eSSatish Balay   {
578e5c89e4eSSatish Balay     PetscReal x = 1.0;
579e5c89e4eSSatish Balay     int       i =10000000;
580e5c89e4eSSatish Balay     while (i--) x++;  /* cannot attach to sleeper */
581e5c89e4eSSatish Balay   }
582e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
583e5c89e4eSSatish Balay   /*
584e5c89e4eSSatish Balay       IBM sleep may return at anytime, hence must see if there is more time to sleep
585e5c89e4eSSatish Balay   */
586e5c89e4eSSatish Balay   {
587e5c89e4eSSatish Balay     int left = sleeptime;
588a297a907SKarl Rupp     while (left > 0) left = sleep(left) - 1;
589e5c89e4eSSatish Balay   }
590e5c89e4eSSatish Balay #else
591e5c89e4eSSatish Balay   PetscSleep(sleeptime);
592e5c89e4eSSatish Balay #endif
593e5c89e4eSSatish Balay   PetscFunctionReturn(0);
594e5c89e4eSSatish Balay }
595