xref: /petsc/src/sys/error/adebug.c (revision 63a3b9bc7a1f24f247904ccba9383635fe6abade)
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;
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 
80c823fc1fSBarry Smith .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 
97e5c89e4eSSatish Balay .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 
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;
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 
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:
2019566063dSJacob Faibussowitsch     Since this can be called by the error handler should it be calling SETERRQ() and PetscCall()?
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   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
220*63a3b9bcSJacob Faibussowitsch   if (PetscUnlikely(PetscGetDisplay(display,sizeof(display)))) {
2215f80ce2aSJacob Faibussowitsch     (*PetscErrorPrintf)("Cannot determine display\n");
2225f80ce2aSJacob Faibussowitsch     PetscFunctionReturn(PETSC_ERR_SYS);
2235f80ce2aSJacob Faibussowitsch   }
224*63a3b9bcSJacob 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)
244*63a3b9bcSJacob 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];
3149566063dSJacob Faibussowitsch           PetscCall(PetscSNPrintf(command,sizeof(command),"osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s  %s \"'\n",pid,program));
3159566063dSJacob Faibussowitsch           PetscCall(PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",NULL));
316c823fc1fSBarry Smith           exit(0);
317c823fc1fSBarry Smith         }
318c823fc1fSBarry Smith 
3199566063dSJacob Faibussowitsch         PetscCall(PetscStrncmp(DebugTerminal,"screen",6,&cmp));
3209566063dSJacob Faibussowitsch         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal,"gnome-terminal",6,&cmp));
3215e96ac45SJed Brown         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3225e96ac45SJed Brown         args[j++] = tmp = DebugTerminal;
3235e96ac45SJed Brown         if (display[0]) {
3245e96ac45SJed Brown           args[j++] = "-display"; args[j++] = display;
3255e96ac45SJed Brown         }
3265e96ac45SJed Brown         while (*tmp) {
3279566063dSJacob Faibussowitsch           PetscCall(PetscStrchr(tmp,' ',&tmp1));
3285e96ac45SJed Brown           if (!tmp1) break;
3295e96ac45SJed Brown           *tmp1     = 0;
3305e96ac45SJed Brown           tmp       = tmp1+1;
3315e96ac45SJed Brown           args[j++] = tmp;
3325e96ac45SJed Brown         }
3335e96ac45SJed Brown       }
334b59f628eSBarry Smith       args[j++] = PetscDebugger;
3355e96ac45SJed Brown       jj = j;
336bf4d2887SBarry Smith       /* this is for default gdb */
337bf4d2887SBarry Smith       args[j++] = program;
338bf4d2887SBarry Smith       args[j++] = pid;
339bf4d2887SBarry Smith       args[j++] = NULL;
3405e96ac45SJed Brown 
341e5c89e4eSSatish Balay       if (isidb) {
3425e96ac45SJed Brown         j = jj;
3435e96ac45SJed Brown         args[j++] = "-pid";
3445e96ac45SJed Brown         args[j++] = pid;
3455e96ac45SJed Brown         args[j++] = "-gdb";
3465e96ac45SJed Brown         args[j++] = program;
34702c9f0b5SLisandro Dalcin         args[j++] = NULL;
348e5c89e4eSSatish Balay       }
3490e9bae81SBarry Smith       if (islldb) {
3500e9bae81SBarry Smith         j = jj;
3510e9bae81SBarry Smith         args[j++] = "-p";
3520e9bae81SBarry Smith         args[j++] = pid;
35302c9f0b5SLisandro Dalcin         args[j++] = NULL;
3540e9bae81SBarry Smith       }
355e5c89e4eSSatish Balay       if (isdbx) {
3565e96ac45SJed Brown         j = jj;
3578d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3585e96ac45SJed Brown         args[j++] = "-p";
3595e96ac45SJed Brown         args[j++] = pid;
3605e96ac45SJed Brown         args[j++] = program;
361e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
3625e96ac45SJed Brown         args[j++] = "-l";
3635e96ac45SJed Brown         args[j++] = "ALL";
3645e96ac45SJed Brown         args[j++] = "-P";
3655e96ac45SJed Brown         args[j++] = pid;
3665e96ac45SJed Brown         args[j++] = program;
367e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
3685e96ac45SJed Brown         args[j++] = "-a";
3695e96ac45SJed Brown         args[j++] = pid;
370e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
3715e96ac45SJed Brown         args[j++] = "-pid";
3725e96ac45SJed Brown         args[j++] = pid;
3735e96ac45SJed Brown         args[j++] = program;
374493de400SSatish Balay #else
375493de400SSatish Balay         args[j++] = program;
376493de400SSatish Balay         args[j++] = pid;
3778d359177SBarry Smith #endif
37802c9f0b5SLisandro Dalcin         args[j++] = NULL;
379e5c89e4eSSatish Balay       }
380c823fc1fSBarry Smith       if (UseDebugTerminal) {
381c5888dd7SBarry 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);
382c5888dd7SBarry Smith         else            printf("PETSC: Attaching %s to %s on pid %s on %s\n",PetscDebugger,program,pid,hostname);
383a297a907SKarl Rupp 
3845e96ac45SJed Brown         if (execvp(args[0],(char**)args)  < 0) {
3855e96ac45SJed Brown           perror("Unable to start debugger in xterm");
3865e96ac45SJed Brown           exit(0);
3875e96ac45SJed Brown         }
3885e96ac45SJed Brown       } else {
389c5888dd7SBarry Smith         printf("PETSC: Attaching %s to %s of pid %s on %s\n",PetscDebugger,program,pid,hostname);
390e5c89e4eSSatish Balay         if (execvp(args[0],(char**)args)  < 0) {
391e5c89e4eSSatish Balay           perror("Unable to start debugger");
392e5c89e4eSSatish Balay           exit(0);
393e5c89e4eSSatish Balay         }
394e5c89e4eSSatish Balay       }
395e5c89e4eSSatish Balay     }
396e5c89e4eSSatish Balay   } else {   /* I am the child, continue with user code */
397e5c89e4eSSatish Balay     sleeptime = 10; /* default to sleep waiting for debugger */
3989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(NULL,NULL,"-debugger_pause",&sleeptime,NULL));
399e5c89e4eSSatish Balay     if (sleeptime < 0) sleeptime = -sleeptime;
400e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
401e5c89e4eSSatish Balay     /*
402e5c89e4eSSatish Balay         HP cannot attach process to sleeping debugger, hence count instead
403e5c89e4eSSatish Balay     */
404e5c89e4eSSatish Balay     {
405e5c89e4eSSatish Balay       PetscReal x = 1.0;
406e5c89e4eSSatish Balay       int       i =10000000;
407e5c89e4eSSatish Balay       while (i--) x++;  /* cannot attach to sleeper */
408e5c89e4eSSatish Balay     }
409e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
410e5c89e4eSSatish Balay     /*
411e5c89e4eSSatish Balay         IBM sleep may return at anytime, hence must see if there is more time to sleep
412e5c89e4eSSatish Balay     */
413e5c89e4eSSatish Balay     {
414e5c89e4eSSatish Balay       int left = sleeptime;
415a297a907SKarl Rupp       while (left > 0) left = PetscSleep(left) - 1;
416e5c89e4eSSatish Balay     }
417e5c89e4eSSatish Balay #else
418e5c89e4eSSatish Balay     PetscSleep(sleeptime);
419e5c89e4eSSatish Balay #endif
420e5c89e4eSSatish Balay   }
421e5c89e4eSSatish Balay #endif
422e5c89e4eSSatish Balay   PetscFunctionReturn(0);
423e5c89e4eSSatish Balay }
424e5c89e4eSSatish Balay 
425e5c89e4eSSatish Balay /*@C
426e5c89e4eSSatish Balay    PetscAttachDebuggerErrorHandler - Error handler that attaches
427e5c89e4eSSatish Balay    a debugger to a running process when an error is detected.
428e5c89e4eSSatish Balay    This routine is useful for examining variables, etc.
429e5c89e4eSSatish Balay 
430e5c89e4eSSatish Balay    Not Collective
431e5c89e4eSSatish Balay 
432e5c89e4eSSatish Balay    Input Parameters:
433e32f2f54SBarry Smith +  comm - communicator over which error occurred
434e32f2f54SBarry Smith .  line - the line number of the error (indicated by __LINE__)
435e5c89e4eSSatish Balay .  file - the file in which the error was detected (indicated by __FILE__)
436e5c89e4eSSatish Balay .  message - an error text string, usually just printed to the screen
437e5c89e4eSSatish Balay .  number - the generic error number
438668f157eSBarry Smith .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
439e5c89e4eSSatish Balay -  ctx - error handler context
440e5c89e4eSSatish Balay 
441e5c89e4eSSatish Balay    Options Database Keys:
44245b666d6SBarry Smith +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
44345b666d6SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
444e5c89e4eSSatish Balay 
445e5c89e4eSSatish Balay    Level: developer
446e5c89e4eSSatish Balay 
447e5c89e4eSSatish Balay    Notes:
448c4fb7a8fSRichard Tran Mills    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
449e5c89e4eSSatish Balay    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay    Most users need not directly employ this routine and the other error
452e5c89e4eSSatish Balay    handlers, but can instead use the simplified interface SETERR, which has
453e5c89e4eSSatish Balay    the calling sequence
454e32f2f54SBarry Smith $     SETERRQ(PETSC_COMM_SELF,number,p,message)
455e5c89e4eSSatish Balay 
456e5c89e4eSSatish Balay    Notes for experienced users:
457e5c89e4eSSatish Balay    Use PetscPushErrorHandler() to set the desired error handler.  The
458e5c89e4eSSatish Balay    currently available PETSc error handlers are
459e5c89e4eSSatish Balay $    PetscTraceBackErrorHandler()
460e5c89e4eSSatish Balay $    PetscAttachDebuggerErrorHandler()
461e5c89e4eSSatish Balay $    PetscAbortErrorHandler()
462e5c89e4eSSatish Balay    or you may write your own.
463e5c89e4eSSatish Balay 
46445b666d6SBarry Smith .seealso:  PetscSetDebuggerFromString(), PetscSetDebugger(), PetscSetDefaultDebugger(), PetscError(), PetscPushErrorHandler(), PetscPopErrorHandler(), PetscTraceBackErrorHandler(),
465c823fc1fSBarry Smith            PetscAbortErrorHandler(), PetscMPIAbortErrorHandler(), PetscEmacsClientErrorHandler(), PetscReturnErrorHandler(), PetscSetDebugTermainal()
466e5c89e4eSSatish Balay @*/
467efca3c55SSatish Balay PetscErrorCode  PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char *fun,const char *file,PetscErrorCode num,PetscErrorType p,const char *mess,void *ctx)
468e5c89e4eSSatish Balay {
469e5c89e4eSSatish Balay   PetscErrorCode ierr;
470e5c89e4eSSatish Balay 
471e5c89e4eSSatish Balay   PetscFunctionBegin;
472e5c89e4eSSatish Balay   if (!fun) fun = "User provided function";
473e5c89e4eSSatish Balay   if (!mess) mess = " ";
474e5c89e4eSSatish Balay 
4752f307e7aSJunchao Zhang   (*PetscErrorPrintf)("%s() at %s:%d %s\n",fun,file,line,mess);
476e5c89e4eSSatish Balay 
477e5c89e4eSSatish Balay   ierr = PetscAttachDebugger();
478a297a907SKarl Rupp   if (ierr) abort(); /* call abort because don't want to kill other MPI processes that may successfully attach to debugger */
479e5c89e4eSSatish Balay   PetscFunctionReturn(0);
480e5c89e4eSSatish Balay }
481e5c89e4eSSatish Balay 
482e5c89e4eSSatish Balay /*@C
483e5c89e4eSSatish Balay    PetscStopForDebugger - Prints a message to the screen indicating how to
484e5c89e4eSSatish Balay          attach to the process with the debugger and then waits for the
485e5c89e4eSSatish Balay          debugger to attach.
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay    Not Collective
488e5c89e4eSSatish Balay 
4891f690a00SBarry Smith    Options Database:
4901f690a00SBarry Smith .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
4911f690a00SBarry Smith 
4928d359177SBarry Smith    Level: developer
493e5c89e4eSSatish Balay 
49495452b02SPatrick Sanan    Notes:
49595452b02SPatrick Sanan     This is likely never needed since PetscAttachDebugger() is easier to use and seems to always work.
4968d359177SBarry Smith 
49795452b02SPatrick Sanan    Developer Notes:
4989566063dSJacob Faibussowitsch     Since this can be called by the error handler, should it be calling SETERRQ() and PetscCall()?
499f35f84d1SBarry Smith 
500e5c89e4eSSatish Balay .seealso: PetscSetDebugger(), PetscAttachDebugger()
501e5c89e4eSSatish Balay @*/
5027087cfbeSBarry Smith PetscErrorCode  PetscStopForDebugger(void)
503e5c89e4eSSatish Balay {
504e5c89e4eSSatish Balay   PetscErrorCode ierr;
505e5c89e4eSSatish Balay   PetscInt       sleeptime=0;
506e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
50751ec2c11SGlenn Hammond   int            ppid;
508e5c89e4eSSatish Balay   PetscMPIInt    rank;
509e5c89e4eSSatish Balay   char           program[PETSC_MAX_PATH_LEN],hostname[256];
5108d359177SBarry Smith   PetscBool      isdbx,isxldb,isxxgdb,isddd,iskdbg,isups,isxdb,islldb;
511e5c89e4eSSatish Balay #endif
512e5c89e4eSSatish Balay 
513e5c89e4eSSatish Balay   PetscFunctionBegin;
514e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
515e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
516e5c89e4eSSatish Balay #else
517e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
518f35f84d1SBarry Smith   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
519589a23caSBarry Smith   ierr = PetscGetHostName(hostname,sizeof(hostname));
520e5c89e4eSSatish Balay   if (ierr) {
521e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
522e5c89e4eSSatish Balay     PetscFunctionReturn(0);
523e5c89e4eSSatish Balay   }
524e5c89e4eSSatish Balay 
525589a23caSBarry Smith   ierr = PetscGetProgramName(program,sizeof(program));
526e5c89e4eSSatish Balay   if (ierr) {
527e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
528e5c89e4eSSatish Balay     PetscFunctionReturn(0);
529e5c89e4eSSatish Balay   }
530e5c89e4eSSatish Balay   if (!program[0]) {
531e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
532e5c89e4eSSatish Balay     PetscFunctionReturn(0);
533e5c89e4eSSatish Balay   }
534e5c89e4eSSatish Balay 
535e5c89e4eSSatish Balay   ppid = getpid();
536e5c89e4eSSatish Balay 
5379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xxgdb",&isxxgdb));
5389566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"ddd",&isddd));
5399566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"kdbg",&iskdbg));
5409566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"ups",&isups));
5419566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xldb",&isxldb));
5429566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"xdb",&isxdb));
5439566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"dbx",&isdbx));
5449566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger,"lldb",&islldb));
545e5c89e4eSSatish Balay 
546c5888dd7SBarry Smith   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
547c5888dd7SBarry Smith   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n",rank,hostname,PetscDebugger,ppid,program);
548c5888dd7SBarry Smith   else if (islldb) printf("[%d]%s>>%s -p %d\n",rank,hostname,PetscDebugger,ppid);
5498d359177SBarry Smith   else if (isdbx) {
550e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
551c5888dd7SBarry Smith      printf("[%d]%s>>%s -p %d %s\n",rank,hostname,PetscDebugger,ppid,program);
552e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
553c5888dd7SBarry Smith      printf("[%d]%s>>%s -l ALL -P %d %s\n",rank,hostname,PetscDebugger,ppid,program);
554e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
555c5888dd7SBarry Smith      printf("[%d]%s>>%s -a %d\n",rank,hostname,PetscDebugger,ppid);
556e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
557c5888dd7SBarry Smith      printf("[%d]%s>>%s -pid %d %s\n",rank,hostname,PetscDebugger,ppid,program);
558e5c89e4eSSatish Balay #else
559c5888dd7SBarry Smith      printf("[%d]%s>>%s %s %d\n",rank,hostname,PetscDebugger,program,ppid);
560e5c89e4eSSatish Balay #endif
5618d359177SBarry Smith   }
562e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
563e5c89e4eSSatish Balay 
564f35f84d1SBarry Smith   fflush(stdout); /* ignore error because may already be in error handler */
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay   sleeptime = 25; /* default to sleep waiting for debugger */
567c5929fdfSBarry Smith   PetscOptionsGetInt(NULL,NULL,"-debugger_pause",&sleeptime,NULL); /* ignore error because may already be in error handler */
568e5c89e4eSSatish Balay   if (sleeptime < 0) sleeptime = -sleeptime;
569e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
570e5c89e4eSSatish Balay   /*
571e5c89e4eSSatish Balay       HP cannot attach process to sleeping debugger, hence count instead
572e5c89e4eSSatish Balay   */
573e5c89e4eSSatish Balay   {
574e5c89e4eSSatish Balay     PetscReal x = 1.0;
575e5c89e4eSSatish Balay     int       i =10000000;
576e5c89e4eSSatish Balay     while (i--) x++;  /* cannot attach to sleeper */
577e5c89e4eSSatish Balay   }
578e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
579e5c89e4eSSatish Balay   /*
580e5c89e4eSSatish Balay       IBM sleep may return at anytime, hence must see if there is more time to sleep
581e5c89e4eSSatish Balay   */
582e5c89e4eSSatish Balay   {
583e5c89e4eSSatish Balay     int left = sleeptime;
584a297a907SKarl Rupp     while (left > 0) left = sleep(left) - 1;
585e5c89e4eSSatish Balay   }
586e5c89e4eSSatish Balay #else
587e5c89e4eSSatish Balay   PetscSleep(sleeptime);
588e5c89e4eSSatish Balay #endif
589e5c89e4eSSatish Balay   PetscFunctionReturn(0);
590e5c89e4eSSatish Balay }
591