xref: /petsc/src/sys/error/adebug.c (revision 49c86fc7db8873518b7539cf8a78d57cfd90852a)
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 
47db781477SPatrick Sanan .seealso: `PetscSetDebugger()`
485e96ac45SJed Brown @*/
497087cfbeSBarry Smith PetscErrorCode PetscSetDebugTerminal(const char terminal[])
505e96ac45SJed Brown {
51c823fc1fSBarry Smith   PetscBool xterm;
525e96ac45SJed Brown 
535e96ac45SJed Brown   PetscFunctionBegin;
549566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(DebugTerminal,terminal,sizeof(DebugTerminal)));
559566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(terminal,"xterm",&xterm));
569566063dSJacob Faibussowitsch   if (xterm) PetscCall(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 
80db781477SPatrick Sanan .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
81e5c89e4eSSatish Balay @*/
82c823fc1fSBarry Smith PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
83e5c89e4eSSatish Balay {
84e5c89e4eSSatish Balay   PetscFunctionBegin;
859566063dSJacob Faibussowitsch   if (debugger) PetscCall(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 
97db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`
98e5c89e4eSSatish Balay @*/
997087cfbeSBarry Smith PetscErrorCode PetscSetDefaultDebugger(void)
100e5c89e4eSSatish Balay {
101e5c89e4eSSatish Balay   PetscFunctionBegin;
1024211eb48SBarry Smith #if defined(PETSC_USE_DEBUGGER)
1039566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER,PETSC_TRUE));
104e5c89e4eSSatish Balay #endif
105c823fc1fSBarry Smith #if defined(__APPLE__)
1069566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugTerminal("Terminal"));
107c823fc1fSBarry Smith #else
1089566063dSJacob Faibussowitsch   PetscCall(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;
1199566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, defaultDbg, &f));
120e5c89e4eSSatish Balay   if (f) {
1219566063dSJacob Faibussowitsch     PetscCall(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 
136db781477SPatrick Sanan .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;
1459566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "noxterm", &f));
146c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1479566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "ddd", &f));
148c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1499566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "noterminal", &f));
150c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1519566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xdb",      string, &debugger));
1529566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("dbx",      string, &debugger));
1539566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xldb",     string, &debugger));
1549566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("gdb",      string, &debugger));
1559566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
1569566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("idb",      string, &debugger));
1579566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xxgdb",    string, &debugger));
1589566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("ddd",      string, &debugger));
1599566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("kdbg",     string, &debugger));
1609566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("ups",      string, &debugger));
1619566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
1629566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("pgdbg",    string, &debugger));
1639566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("pathdb",   string, &debugger));
1649566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("lldb",     string, &debugger));
1659566063dSJacob Faibussowitsch   PetscCall(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 
181db781477SPatrick Sanan .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:
2019566063dSJacob Faibussowitsch     Since this can be called by the error handler should it be calling SETERRQ() and PetscCall()?
202f35f84d1SBarry Smith 
203db781477SPatrick Sanan .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   char      program[PETSC_MAX_PATH_LEN],display[256],hostname[64];
211e5c89e4eSSatish Balay #endif
212e5c89e4eSSatish Balay 
213e5c89e4eSSatish Balay   PetscFunctionBegin;
214e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
215e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger\n");
216e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
217e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
21841e02c4dSJunchao Zhang   PETSCABORT(PETSC_COMM_WORLD,PETSC_ERR_SUP_SYS);
219e5c89e4eSSatish Balay #else
22063a3b9bcSJacob Faibussowitsch   if (PetscUnlikely(PetscGetDisplay(display,sizeof(display)))) {
2215f80ce2aSJacob Faibussowitsch     (*PetscErrorPrintf)("Cannot determine display\n");
2225f80ce2aSJacob Faibussowitsch     PetscFunctionReturn(PETSC_ERR_SYS);
2235f80ce2aSJacob Faibussowitsch   }
22463a3b9bcSJacob Faibussowitsch   if (PetscUnlikely(PetscGetProgramName(program,sizeof(program)))) {
225e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
226a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
227e5c89e4eSSatish Balay   }
2285f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(!program[0])) {
229e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name\n");
230a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
231e5c89e4eSSatish Balay   }
232e5c89e4eSSatish Balay   child = (int)fork();
2335f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(child < 0)) {
234a995a477SBarry Smith     (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
235a995a477SBarry Smith     PetscFunctionReturn(PETSC_ERR_SYS);
236e5c89e4eSSatish Balay   }
237bf4d2887SBarry Smith   petscindebugger = PETSC_TRUE;
238e5c89e4eSSatish Balay 
239e5c89e4eSSatish Balay   /*
240e5c89e4eSSatish Balay       Swap role the parent and child. This is (I think) so that control c typed
241e5c89e4eSSatish Balay     in the debugger goes to the correct process.
242e5c89e4eSSatish Balay   */
243234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
24463a3b9bcSJacob Faibussowitsch   child = child ? 0 : (int)getppid();
245234acd79SBarry Smith #endif
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay   if (child) { /* I am the parent, will run the debugger */
248e5c89e4eSSatish Balay     const char *args[10];
249e5c89e4eSSatish Balay     char       pid[10];
2505e96ac45SJed Brown     PetscInt   j,jj;
2510e9bae81SBarry Smith     PetscBool  isdbx,isidb,isxldb,isxxgdb,isups,isxdb,isworkshop,isddd,iskdbg,islldb;
252e5c89e4eSSatish Balay 
2539566063dSJacob Faibussowitsch     PetscCall(PetscGetHostName(hostname,sizeof(hostname)));
254e5c89e4eSSatish Balay     /*
255e5c89e4eSSatish Balay          We need to send a continue signal to the "child" process on the
256e5c89e4eSSatish Balay        alpha, otherwise it just stays off forever
257e5c89e4eSSatish Balay     */
258e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
259e5c89e4eSSatish Balay     kill(child,SIGCONT);
260e5c89e4eSSatish Balay #endif
261e5c89e4eSSatish Balay     sprintf(pid,"%d",child);
262e5c89e4eSSatish Balay 
2639566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
2649566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"ddd",&isddd));
2659566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
2669566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"ups",&isups));
2679566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
2689566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
2699566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
2709566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"idb",&isidb));
2719566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"workshop",&isworkshop));
2729566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger,"lldb",&islldb));
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay     if (isxxgdb || isups || isddd) {
275e5c89e4eSSatish Balay       args[1] = program; args[2] = pid; args[3] = "-display";
27602c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[4] = display; args[5] = NULL;
277c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
278e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
279e5c89e4eSSatish Balay         perror("Unable to start debugger");
280e5c89e4eSSatish Balay         exit(0);
281e5c89e4eSSatish Balay       }
282bf902449SSatish Balay     } else if (iskdbg) {
283bf902449SSatish Balay       args[1] = "-p"; args[2] = pid; args[3] = program;  args[4] = "-display";
28402c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
285c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[3],pid,hostname);
286bf902449SSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
287bf902449SSatish Balay         perror("Unable to start debugger");
288bf902449SSatish Balay         exit(0);
289bf902449SSatish Balay       }
290e5c89e4eSSatish Balay     } else if (isxldb) {
291e5c89e4eSSatish Balay       args[1] = "-a"; args[2] = pid; args[3] = program;  args[4] = "-display";
29202c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = display; args[6] = NULL;
293c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n",args[0],args[1],pid,hostname);
294e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
295e5c89e4eSSatish Balay         perror("Unable to start debugger");
296e5c89e4eSSatish Balay         exit(0);
297e5c89e4eSSatish Balay       }
298e5c89e4eSSatish Balay     } else if (isworkshop) {
299e5c89e4eSSatish Balay       args[1] = "-s"; args[2] = pid; args[3] = "-D"; args[4] = "-";
30002c9f0b5SLisandro Dalcin       args[0] = PetscDebugger; args[5] = pid; args[6] = "-display"; args[7] = display; args[8] = NULL;
301c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s on %s\n",args[0],pid,hostname);
302e5c89e4eSSatish Balay       if (execvp(args[0],(char**)args)  < 0) {
303e5c89e4eSSatish Balay         perror("Unable to start debugger");
304e5c89e4eSSatish Balay         exit(0);
305e5c89e4eSSatish Balay       }
3065e96ac45SJed Brown     } else {
3075e96ac45SJed Brown       j = 0;
308c823fc1fSBarry Smith       if (UseDebugTerminal) {
309ace3abfcSBarry Smith         PetscBool cmp;
3105e96ac45SJed Brown         char      *tmp,*tmp1;
3119566063dSJacob Faibussowitsch         PetscCall(PetscStrncmp(DebugTerminal,"Terminal",8,&cmp));
312c823fc1fSBarry Smith         if (cmp) {
313c823fc1fSBarry Smith           char command[1024];
3149483a8a2SBarry Smith           if (islldb) PetscCall(PetscSNPrintf(command,sizeof(command),"osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s \"'\n",pid));
3159483a8a2SBarry Smith           else {
3169483a8a2SBarry Smith             char fullprogram[PETSC_MAX_PATH_LEN];
3179483a8a2SBarry Smith             PetscCall(PetscGetFullPath(program,fullprogram,sizeof(fullprogram)));
3189483a8a2SBarry Smith             PetscCall(PetscSNPrintf(command,sizeof(command),"osascript -e 'tell app \"Terminal\" to do script \"%s  %s %s \"'\n",PetscDebugger,fullprogram,pid));
3199483a8a2SBarry Smith           }
3209566063dSJacob Faibussowitsch           PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",NULL));
321c823fc1fSBarry Smith           exit(0);
322c823fc1fSBarry Smith         }
323c823fc1fSBarry Smith 
3249566063dSJacob Faibussowitsch         PetscCall(PetscStrncmp(DebugTerminal,"screen",6,&cmp));
3259566063dSJacob Faibussowitsch         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp));
3265e96ac45SJed Brown         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3275e96ac45SJed Brown         args[j++] = tmp = DebugTerminal;
3285e96ac45SJed Brown         if (display[0]) {
3295e96ac45SJed Brown           args[j++] = "-display"; args[j++] = display;
3305e96ac45SJed Brown         }
3315e96ac45SJed Brown         while (*tmp) {
3329566063dSJacob Faibussowitsch           PetscCall(PetscStrchr(tmp,' ',&tmp1));
3335e96ac45SJed Brown           if (!tmp1) break;
3345e96ac45SJed Brown           *tmp1     = 0;
3355e96ac45SJed Brown           tmp       = tmp1+1;
3365e96ac45SJed Brown           args[j++] = tmp;
3375e96ac45SJed Brown         }
3385e96ac45SJed Brown       }
339b59f628eSBarry Smith       args[j++] = PetscDebugger;
3405e96ac45SJed Brown       jj = j;
341bf4d2887SBarry Smith       /* this is for default gdb */
342bf4d2887SBarry Smith       args[j++] = program;
343bf4d2887SBarry Smith       args[j++] = pid;
344bf4d2887SBarry Smith       args[j++] = NULL;
3455e96ac45SJed Brown 
346e5c89e4eSSatish Balay       if (isidb) {
3475e96ac45SJed Brown         j = jj;
3485e96ac45SJed Brown         args[j++] = "-pid";
3495e96ac45SJed Brown         args[j++] = pid;
3505e96ac45SJed Brown         args[j++] = "-gdb";
3515e96ac45SJed Brown         args[j++] = program;
35202c9f0b5SLisandro Dalcin         args[j++] = NULL;
353e5c89e4eSSatish Balay       }
3540e9bae81SBarry Smith       if (islldb) {
3550e9bae81SBarry Smith         j = jj;
3560e9bae81SBarry Smith         args[j++] = "-p";
3570e9bae81SBarry Smith         args[j++] = pid;
35802c9f0b5SLisandro Dalcin         args[j++] = NULL;
3590e9bae81SBarry Smith       }
360e5c89e4eSSatish Balay       if (isdbx) {
3615e96ac45SJed Brown         j = jj;
3628d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3635e96ac45SJed Brown         args[j++] = "-p";
3645e96ac45SJed Brown         args[j++] = pid;
3655e96ac45SJed Brown         args[j++] = program;
366e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
3675e96ac45SJed Brown         args[j++] = "-l";
3685e96ac45SJed Brown         args[j++] = "ALL";
3695e96ac45SJed Brown         args[j++] = "-P";
3705e96ac45SJed Brown         args[j++] = pid;
3715e96ac45SJed Brown         args[j++] = program;
372e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
3735e96ac45SJed Brown         args[j++] = "-a";
3745e96ac45SJed Brown         args[j++] = pid;
375e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
3765e96ac45SJed Brown         args[j++] = "-pid";
3775e96ac45SJed Brown         args[j++] = pid;
3785e96ac45SJed Brown         args[j++] = program;
379493de400SSatish Balay #else
380493de400SSatish Balay         args[j++] = program;
381493de400SSatish Balay         args[j++] = pid;
3828d359177SBarry Smith #endif
38302c9f0b5SLisandro Dalcin         args[j++] = NULL;
384e5c89e4eSSatish Balay       }
385c823fc1fSBarry Smith       if (UseDebugTerminal) {
386c5888dd7SBarry 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);
387c5888dd7SBarry Smith         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
388a297a907SKarl Rupp 
3895e96ac45SJed Brown         if (execvp(args[0],(char**)args)  < 0) {
3905e96ac45SJed Brown           perror("Unable to start debugger in xterm");
3915e96ac45SJed Brown           exit(0);
3925e96ac45SJed Brown         }
3935e96ac45SJed Brown       } else {
394c5888dd7SBarry Smith         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
395e5c89e4eSSatish Balay         if (execvp(args[0],(char**)args)  < 0) {
396e5c89e4eSSatish Balay           perror("Unable to start debugger");
397e5c89e4eSSatish Balay           exit(0);
398e5c89e4eSSatish Balay         }
399e5c89e4eSSatish Balay       }
400e5c89e4eSSatish Balay     }
401e5c89e4eSSatish Balay   } else {   /* I am the child, continue with user code */
402e5c89e4eSSatish Balay     sleeptime = 10; /* default to sleep waiting for debugger */
4039566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL));
404e5c89e4eSSatish Balay     if (sleeptime < 0) sleeptime = -sleeptime;
405e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
406e5c89e4eSSatish Balay     /*
407e5c89e4eSSatish Balay         HP cannot attach process to sleeping debugger, hence count instead
408e5c89e4eSSatish Balay     */
409e5c89e4eSSatish Balay     {
410e5c89e4eSSatish Balay       PetscReal x = 1.0;
411e5c89e4eSSatish Balay       int       i =10000000;
412e5c89e4eSSatish Balay       while (i--) x++;  /* cannot attach to sleeper */
413e5c89e4eSSatish Balay     }
414e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
415e5c89e4eSSatish Balay     /*
416e5c89e4eSSatish Balay         IBM sleep may return at anytime, hence must see if there is more time to sleep
417e5c89e4eSSatish Balay     */
418e5c89e4eSSatish Balay     {
419e5c89e4eSSatish Balay       int left = sleeptime;
420a297a907SKarl Rupp       while (left > 0) left = PetscSleep(left) - 1;
421e5c89e4eSSatish Balay     }
422e5c89e4eSSatish Balay #else
423e5c89e4eSSatish Balay     PetscSleep(sleeptime);
424e5c89e4eSSatish Balay #endif
425e5c89e4eSSatish Balay   }
426e5c89e4eSSatish Balay #endif
427e5c89e4eSSatish Balay   PetscFunctionReturn(0);
428e5c89e4eSSatish Balay }
429e5c89e4eSSatish Balay 
430e5c89e4eSSatish Balay /*@C
431e5c89e4eSSatish Balay    PetscAttachDebuggerErrorHandler - Error handler that attaches
432e5c89e4eSSatish Balay    a debugger to a running process when an error is detected.
433e5c89e4eSSatish Balay    This routine is useful for examining variables, etc.
434e5c89e4eSSatish Balay 
435e5c89e4eSSatish Balay    Not Collective
436e5c89e4eSSatish Balay 
437e5c89e4eSSatish Balay    Input Parameters:
438e32f2f54SBarry Smith +  comm - communicator over which error occurred
439e32f2f54SBarry Smith .  line - the line number of the error (indicated by __LINE__)
440e5c89e4eSSatish Balay .  file - the file in which the error was detected (indicated by __FILE__)
441e5c89e4eSSatish Balay .  message - an error text string, usually just printed to the screen
442e5c89e4eSSatish Balay .  number - the generic error number
443668f157eSBarry Smith .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
444e5c89e4eSSatish Balay -  ctx - error handler context
445e5c89e4eSSatish Balay 
446e5c89e4eSSatish Balay    Options Database Keys:
44745b666d6SBarry Smith +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
44845b666d6SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
449e5c89e4eSSatish Balay 
450e5c89e4eSSatish Balay    Level: developer
451e5c89e4eSSatish Balay 
452e5c89e4eSSatish Balay    Notes:
453c4fb7a8fSRichard Tran Mills    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
454e5c89e4eSSatish Balay    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
455e5c89e4eSSatish Balay 
456e5c89e4eSSatish Balay    Most users need not directly employ this routine and the other error
457e5c89e4eSSatish Balay    handlers, but can instead use the simplified interface SETERR, which has
458e5c89e4eSSatish Balay    the calling sequence
459e32f2f54SBarry Smith $     SETERRQ(PETSC_COMM_SELF,number,p,message)
460e5c89e4eSSatish Balay 
461e5c89e4eSSatish Balay    Notes for experienced users:
462e5c89e4eSSatish Balay    Use PetscPushErrorHandler() to set the desired error handler.  The
463e5c89e4eSSatish Balay    currently available PETSc error handlers are
464e5c89e4eSSatish Balay $    PetscTraceBackErrorHandler()
465e5c89e4eSSatish Balay $    PetscAttachDebuggerErrorHandler()
466e5c89e4eSSatish Balay $    PetscAbortErrorHandler()
467e5c89e4eSSatish Balay    or you may write your own.
468e5c89e4eSSatish Balay 
469db781477SPatrick Sanan .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
470db781477SPatrick Sanan           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
471e5c89e4eSSatish Balay @*/
472efca3c55SSatish Balay PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
473e5c89e4eSSatish Balay {
474e5c89e4eSSatish Balay   PetscErrorCode ierr;
475e5c89e4eSSatish Balay 
476e5c89e4eSSatish Balay   PetscFunctionBegin;
477e5c89e4eSSatish Balay   if (!mess) mess = " ";
478e5c89e4eSSatish Balay 
479*49c86fc7SBarry Smith   if (fun) (*PetscErrorPrintf)("%s() at %s:%d %s\n",fun,file,line,mess);
480*49c86fc7SBarry Smith   else  (*PetscErrorPrintf)("%s:%d %s\n",file,line,mess);
481e5c89e4eSSatish Balay 
482e5c89e4eSSatish Balay   ierr = PetscAttachDebugger();
483a297a907SKarl Rupp   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
484e5c89e4eSSatish Balay   PetscFunctionReturn(0);
485e5c89e4eSSatish Balay }
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay /*@C
488e5c89e4eSSatish Balay    PetscStopForDebugger - Prints a message to the screen indicating how to
489e5c89e4eSSatish Balay          attach to the process with the debugger and then waits for the
490e5c89e4eSSatish Balay          debugger to attach.
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay    Not Collective
493e5c89e4eSSatish Balay 
4941f690a00SBarry Smith    Options Database:
4951f690a00SBarry Smith .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
4961f690a00SBarry Smith 
4978d359177SBarry Smith    Level: developer
498e5c89e4eSSatish Balay 
49995452b02SPatrick Sanan    Notes:
50095452b02SPatrick Sanan     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
5018d359177SBarry Smith 
50295452b02SPatrick Sanan    Developer Notes:
5039566063dSJacob Faibussowitsch     Since this can be called by the error handler, should it be calling SETERRQ() and PetscCall()?
504f35f84d1SBarry Smith 
505db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
506e5c89e4eSSatish Balay @*/
5077087cfbeSBarry Smith PetscErrorCode  PetscStopForDebugger(void)
508e5c89e4eSSatish Balay {
509e5c89e4eSSatish Balay   PetscErrorCode ierr;
510e5c89e4eSSatish Balay   PetscInt       sleeptime=0;
511e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
51251ec2c11SGlenn Hammond   int            ppid;
513e5c89e4eSSatish Balay   PetscMPIInt    rank;
514e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],hostname[256];
5158d359177SBarry Smith   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
516e5c89e4eSSatish Balay #endif
517e5c89e4eSSatish Balay 
518e5c89e4eSSatish Balay   PetscFunctionBegin;
519e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
520e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
521e5c89e4eSSatish Balay #else
522e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
523f35f84d1SBarry Smith   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
524589a23caSBarry Smith   ierr = PetscGetHostName(hostname,sizeof(hostname));
525e5c89e4eSSatish Balay   if (ierr) {
526e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
527e5c89e4eSSatish Balay     PetscFunctionReturn(0);
528e5c89e4eSSatish Balay   }
529e5c89e4eSSatish Balay 
530589a23caSBarry Smith   ierr = PetscGetProgramName(program,sizeof(program));
531e5c89e4eSSatish Balay   if (ierr) {
532e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
533e5c89e4eSSatish Balay     PetscFunctionReturn(0);
534e5c89e4eSSatish Balay   }
535e5c89e4eSSatish Balay   if (!program[0]) {
536e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
537e5c89e4eSSatish Balay     PetscFunctionReturn(0);
538e5c89e4eSSatish Balay   }
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay   ppid = getpid();
541e5c89e4eSSatish Balay 
5429566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
5439566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"ddd",&isddd));
5449566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
5459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"ups",&isups));
5469566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
5479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
5489566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
5499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"lldb",&islldb));
550e5c89e4eSSatish Balay 
551c5888dd7SBarry Smith   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
552c5888dd7SBarry Smith   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
553c5888dd7SBarry Smith   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
5548d359177SBarry Smith   else if (isdbx) {
555e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
556c5888dd7SBarry Smith      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
557e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
558c5888dd7SBarry Smith      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
559e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
560c5888dd7SBarry Smith      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
561e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
562c5888dd7SBarry Smith      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
563e5c89e4eSSatish Balay #else
564c5888dd7SBarry Smith      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
565e5c89e4eSSatish Balay #endif
5668d359177SBarry Smith   }
567e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
568e5c89e4eSSatish Balay 
569f35f84d1SBarry Smith   fflush(stdout); /* ignore error because may already be in error handler */
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay   sleeptime = 25; /* default to sleep waiting for debugger */
572c5929fdfSBarry Smith   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
573e5c89e4eSSatish Balay   if (sleeptime < 0) sleeptime = -sleeptime;
574e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
575e5c89e4eSSatish Balay   /*
576e5c89e4eSSatish Balay       HP cannot attach process to sleeping debugger, hence count instead
577e5c89e4eSSatish Balay   */
578e5c89e4eSSatish Balay   {
579e5c89e4eSSatish Balay     PetscReal x = 1.0;
580e5c89e4eSSatish Balay     int       i =10000000;
581e5c89e4eSSatish Balay     while (i--) x++;  /* cannot attach to sleeper */
582e5c89e4eSSatish Balay   }
583e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
584e5c89e4eSSatish Balay   /*
585e5c89e4eSSatish Balay       IBM sleep may return at anytime, hence must see if there is more time to sleep
586e5c89e4eSSatish Balay   */
587e5c89e4eSSatish Balay   {
588e5c89e4eSSatish Balay     int left = sleeptime;
589a297a907SKarl Rupp     while (left > 0) left = sleep(left) - 1;
590e5c89e4eSSatish Balay   }
591e5c89e4eSSatish Balay #else
592e5c89e4eSSatish Balay   PetscSleep(sleeptime);
593e5c89e4eSSatish Balay #endif
594e5c89e4eSSatish Balay   PetscFunctionReturn(0);
595e5c89e4eSSatish Balay }
596