xref: /petsc/src/sys/error/adebug.c (revision 811af0c4b09a35de4306c442f88bd09fdc09897d)
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 
25*811af0c4SBarry Smith    Input Parameter:
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 
30*811af0c4SBarry Smith    Options Database Key:
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 @*/
499371c9d4SSatish Balay PetscErrorCode PetscSetDebugTerminal(const char terminal[]) {
50c823fc1fSBarry Smith   PetscBool xterm;
515e96ac45SJed Brown 
525e96ac45SJed Brown   PetscFunctionBegin;
539566063dSJacob Faibussowitsch   PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal)));
549566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(terminal, "xterm", &xterm));
559566063dSJacob Faibussowitsch   if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal)));
565e96ac45SJed Brown   PetscFunctionReturn(0);
575e96ac45SJed Brown }
585e96ac45SJed Brown 
59e5c89e4eSSatish Balay /*@C
60e5c89e4eSSatish Balay    PetscSetDebugger - Sets options associated with the debugger.
61e5c89e4eSSatish Balay 
62e5c89e4eSSatish Balay    Not Collective
63e5c89e4eSSatish Balay 
64e5c89e4eSSatish Balay    Input Parameters:
65e5c89e4eSSatish Balay +  debugger - name of debugger, which should be in your path,
66c4fb7a8fSRichard Tran Mills               usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
67e5c89e4eSSatish Balay               supports "xdb", and IBM rs6000 supports "xldb".
68e5c89e4eSSatish Balay 
69c823fc1fSBarry Smith -  usedebugterminal - flag to indicate debugger window, set to either PETSC_TRUE (to indicate
70c823fc1fSBarry Smith             debugger should be started in a new terminal window) or PETSC_FALSE (to start debugger
718d359177SBarry Smith             in initial window (the option PETSC_FALSE makes no sense when using more
728d359177SBarry Smith             than one MPI process.)
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay    Level: developer
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay    Fortran Note:
77e5c89e4eSSatish Balay    This routine is not supported in Fortran.
78e5c89e4eSSatish Balay 
79db781477SPatrick Sanan .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
80e5c89e4eSSatish Balay @*/
819371c9d4SSatish Balay PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal) {
82e5c89e4eSSatish Balay   PetscFunctionBegin;
839566063dSJacob Faibussowitsch   if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger)));
84c823fc1fSBarry Smith   if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
85e5c89e4eSSatish Balay   PetscFunctionReturn(0);
86e5c89e4eSSatish Balay }
87e5c89e4eSSatish Balay 
888d359177SBarry Smith /*@C
89c823fc1fSBarry Smith     PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
90e5c89e4eSSatish Balay 
91e5c89e4eSSatish Balay    Not collective
92e5c89e4eSSatish Balay 
938d359177SBarry Smith     Level: developer
94e5c89e4eSSatish Balay 
95db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`
96e5c89e4eSSatish Balay @*/
979371c9d4SSatish Balay PetscErrorCode PetscSetDefaultDebugger(void) {
98e5c89e4eSSatish Balay   PetscFunctionBegin;
994211eb48SBarry Smith #if defined(PETSC_USE_DEBUGGER)
1009566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE));
101e5c89e4eSSatish Balay #endif
102c823fc1fSBarry Smith #if defined(__APPLE__)
1039566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugTerminal("Terminal"));
104c823fc1fSBarry Smith #else
1059566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugTerminal("xterm"));
106c823fc1fSBarry Smith #endif
107e5c89e4eSSatish Balay   PetscFunctionReturn(0);
108e5c89e4eSSatish Balay }
109e5c89e4eSSatish Balay 
1109371c9d4SSatish Balay static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[]) {
111ace3abfcSBarry Smith   PetscBool exists;
112e5c89e4eSSatish Balay   char     *f;
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay   PetscFunctionBegin;
1159566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, defaultDbg, &f));
116e5c89e4eSSatish Balay   if (f) {
1179566063dSJacob Faibussowitsch     PetscCall(PetscTestFile(string, 'x', &exists));
118a297a907SKarl Rupp     if (exists) *debugger = string;
119a297a907SKarl Rupp     else *debugger = defaultDbg;
120e5c89e4eSSatish Balay   }
121e5c89e4eSSatish Balay   PetscFunctionReturn(0);
122e5c89e4eSSatish Balay }
123e5c89e4eSSatish Balay 
124e5c89e4eSSatish Balay /*@C
125e5c89e4eSSatish Balay     PetscSetDebuggerFromString - Set the complete path for the
126e5c89e4eSSatish Balay        debugger for PETSc to use.
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay    Not collective
129e5c89e4eSSatish Balay 
1307c764164SBarry Smith    Level: developer
131e5c89e4eSSatish Balay 
132db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`
133e5c89e4eSSatish Balay @*/
1349371c9d4SSatish Balay PetscErrorCode PetscSetDebuggerFromString(const char *string) {
1350298fd71SBarry Smith   const char *debugger    = NULL;
136c823fc1fSBarry Smith   PetscBool   useterminal = PETSC_TRUE;
137e5c89e4eSSatish Balay   char       *f;
138e5c89e4eSSatish Balay 
139e5c89e4eSSatish Balay   PetscFunctionBegin;
1409566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "noxterm", &f));
141c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1429566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "ddd", &f));
143c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1449566063dSJacob Faibussowitsch   PetscCall(PetscStrstr(string, "noterminal", &f));
145c823fc1fSBarry Smith   if (f) useterminal = PETSC_FALSE;
1469566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
1479566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
1489566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
1499566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
1509566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
1519566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
1529566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
1539566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
1549566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
1559566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
1569566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
1579566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
1589566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
1599566063dSJacob Faibussowitsch   PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
1609566063dSJacob Faibussowitsch   PetscCall(PetscSetDebugger(debugger, useterminal));
161e5c89e4eSSatish Balay   PetscFunctionReturn(0);
162e5c89e4eSSatish Balay }
163e5c89e4eSSatish Balay 
1642a2a2941SBarry Smith /*@
165*811af0c4SBarry Smith    PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
1662a2a2941SBarry Smith                       of exiting.
1672a2a2941SBarry Smith 
1682a2a2941SBarry Smith    Not Collective
1692a2a2941SBarry Smith 
1702a2a2941SBarry Smith    Level: advanced
1712a2a2941SBarry Smith 
172*811af0c4SBarry Smith    Note:
1732a2a2941SBarry 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
1742a2a2941SBarry Smith       killing the user's debugging sessions.
1752a2a2941SBarry Smith 
176db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
1772a2a2941SBarry Smith @*/
1789371c9d4SSatish Balay PetscErrorCode PetscWaitOnError() {
179baae8e41SSatish Balay   petscwaitonerrorflg = PETSC_TRUE;
1802a2a2941SBarry Smith   return 0;
1812a2a2941SBarry Smith }
182e5c89e4eSSatish Balay 
183e30d2299SSatish Balay /*@
184e5c89e4eSSatish Balay    PetscAttachDebugger - Attaches the debugger to the running process.
185e5c89e4eSSatish Balay 
186e5c89e4eSSatish Balay    Not Collective
187e5c89e4eSSatish Balay 
1881f690a00SBarry Smith    Options Database Keys:
1891f690a00SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n] -debug_terminal xterm or Terminal (for Apple)
1901f690a00SBarry Smith .  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
1911f690a00SBarry Smith 
192e5c89e4eSSatish Balay    Level: advanced
193e5c89e4eSSatish Balay 
194*811af0c4SBarry Smith    Developer Note:
195*811af0c4SBarry Smith     Since this can be called by the error handler should it be calling `SETERRQ()` and `PetscCall()`?
196f35f84d1SBarry Smith 
197db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
198e5c89e4eSSatish Balay @*/
1999371c9d4SSatish Balay PetscErrorCode PetscAttachDebugger(void) {
200ed50d614Sprj- #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
201e5c89e4eSSatish Balay   int       child     = 0;
202a6d0e24fSJed Brown   PetscReal sleeptime = 0;
203e5c89e4eSSatish Balay   char      program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
204e5c89e4eSSatish Balay #endif
205e5c89e4eSSatish Balay 
206e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
207e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger\n");
208e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
209e5c89e4eSSatish Balay   (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
21041e02c4dSJunchao Zhang   PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
211e5c89e4eSSatish Balay #else
21263a3b9bcSJacob Faibussowitsch   if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
2135f80ce2aSJacob Faibussowitsch     (*PetscErrorPrintf)("Cannot determine display\n");
21411cc89d2SBarry Smith     return PETSC_ERR_SYS;
2155f80ce2aSJacob Faibussowitsch   }
21663a3b9bcSJacob Faibussowitsch   if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
21711cc89d2SBarry Smith     (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
21811cc89d2SBarry Smith     return PETSC_ERR_SYS;
219e5c89e4eSSatish Balay   }
2205f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(!program[0])) {
22111cc89d2SBarry Smith     (*PetscErrorPrintf)("Cannot determine program name needed to attach debugger\n");
22211cc89d2SBarry Smith     return PETSC_ERR_SYS;
223e5c89e4eSSatish Balay   }
224e5c89e4eSSatish Balay   child = (int)fork();
2255f80ce2aSJacob Faibussowitsch   if (PetscUnlikely(child < 0)) {
226a995a477SBarry Smith     (*PetscErrorPrintf)("Error in fork() prior to attaching debugger\n");
22711cc89d2SBarry Smith     return PETSC_ERR_SYS;
228e5c89e4eSSatish Balay   }
229bf4d2887SBarry Smith   petscindebugger = PETSC_TRUE;
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay   /*
232e5c89e4eSSatish Balay       Swap role the parent and child. This is (I think) so that control c typed
233e5c89e4eSSatish Balay     in the debugger goes to the correct process.
234e5c89e4eSSatish Balay   */
235234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
23663a3b9bcSJacob Faibussowitsch   child = child ? 0 : (int)getppid();
237234acd79SBarry Smith #endif
238e5c89e4eSSatish Balay 
239e5c89e4eSSatish Balay   if (child) { /* I am the parent, will run the debugger */
240e5c89e4eSSatish Balay     const char *args[10];
241e5c89e4eSSatish Balay     char        pid[10];
2425e96ac45SJed Brown     PetscInt    j, jj;
2430e9bae81SBarry Smith     PetscBool   isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
244e5c89e4eSSatish Balay 
2459566063dSJacob Faibussowitsch     PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
246e5c89e4eSSatish Balay     /*
247e5c89e4eSSatish Balay          We need to send a continue signal to the "child" process on the
248e5c89e4eSSatish Balay        alpha, otherwise it just stays off forever
249e5c89e4eSSatish Balay     */
250e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
251e5c89e4eSSatish Balay     kill(child, SIGCONT);
252e5c89e4eSSatish Balay #endif
253e5c89e4eSSatish Balay     sprintf(pid, "%d", child);
254e5c89e4eSSatish Balay 
2559566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
2569566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
2579566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
2589566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
2599566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
2609566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
2619566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
2629566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
2639566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
2649566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay     if (isxxgdb || isups || isddd) {
2679371c9d4SSatish Balay       args[1] = program;
2689371c9d4SSatish Balay       args[2] = pid;
2699371c9d4SSatish Balay       args[3] = "-display";
2709371c9d4SSatish Balay       args[0] = PetscDebugger;
2719371c9d4SSatish Balay       args[4] = display;
2729371c9d4SSatish Balay       args[5] = NULL;
273c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
274e5c89e4eSSatish Balay       if (execvp(args[0], (char **)args) < 0) {
275e5c89e4eSSatish Balay         perror("Unable to start debugger");
276e5c89e4eSSatish Balay         exit(0);
277e5c89e4eSSatish Balay       }
278bf902449SSatish Balay     } else if (iskdbg) {
2799371c9d4SSatish Balay       args[1] = "-p";
2809371c9d4SSatish Balay       args[2] = pid;
2819371c9d4SSatish Balay       args[3] = program;
2829371c9d4SSatish Balay       args[4] = "-display";
2839371c9d4SSatish Balay       args[0] = PetscDebugger;
2849371c9d4SSatish Balay       args[5] = display;
2859371c9d4SSatish Balay       args[6] = NULL;
286c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
287bf902449SSatish Balay       if (execvp(args[0], (char **)args) < 0) {
288bf902449SSatish Balay         perror("Unable to start debugger");
289bf902449SSatish Balay         exit(0);
290bf902449SSatish Balay       }
291e5c89e4eSSatish Balay     } else if (isxldb) {
2929371c9d4SSatish Balay       args[1] = "-a";
2939371c9d4SSatish Balay       args[2] = pid;
2949371c9d4SSatish Balay       args[3] = program;
2959371c9d4SSatish Balay       args[4] = "-display";
2969371c9d4SSatish Balay       args[0] = PetscDebugger;
2979371c9d4SSatish Balay       args[5] = display;
2989371c9d4SSatish Balay       args[6] = NULL;
299c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
300e5c89e4eSSatish Balay       if (execvp(args[0], (char **)args) < 0) {
301e5c89e4eSSatish Balay         perror("Unable to start debugger");
302e5c89e4eSSatish Balay         exit(0);
303e5c89e4eSSatish Balay       }
304e5c89e4eSSatish Balay     } else if (isworkshop) {
3059371c9d4SSatish Balay       args[1] = "-s";
3069371c9d4SSatish Balay       args[2] = pid;
3079371c9d4SSatish Balay       args[3] = "-D";
3089371c9d4SSatish Balay       args[4] = "-";
3099371c9d4SSatish Balay       args[0] = PetscDebugger;
3109371c9d4SSatish Balay       args[5] = pid;
3119371c9d4SSatish Balay       args[6] = "-display";
3129371c9d4SSatish Balay       args[7] = display;
3139371c9d4SSatish Balay       args[8] = NULL;
314c5888dd7SBarry Smith       printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
315e5c89e4eSSatish Balay       if (execvp(args[0], (char **)args) < 0) {
316e5c89e4eSSatish Balay         perror("Unable to start debugger");
317e5c89e4eSSatish Balay         exit(0);
318e5c89e4eSSatish Balay       }
3195e96ac45SJed Brown     } else {
3205e96ac45SJed Brown       j = 0;
321c823fc1fSBarry Smith       if (UseDebugTerminal) {
322ace3abfcSBarry Smith         PetscBool cmp;
3235e96ac45SJed Brown         char     *tmp, *tmp1;
3249566063dSJacob Faibussowitsch         PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
325c823fc1fSBarry Smith         if (cmp) {
326c823fc1fSBarry Smith           char command[1024];
3279483a8a2SBarry Smith           if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb  -p %s \"'\n", pid));
3289483a8a2SBarry Smith           else {
3299483a8a2SBarry Smith             char fullprogram[PETSC_MAX_PATH_LEN];
3309483a8a2SBarry Smith             PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
3319483a8a2SBarry Smith             PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s  %s %s \"'\n", PetscDebugger, fullprogram, pid));
3329483a8a2SBarry Smith           }
3339566063dSJacob Faibussowitsch           PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
334c823fc1fSBarry Smith           exit(0);
335c823fc1fSBarry Smith         }
336c823fc1fSBarry Smith 
3379566063dSJacob Faibussowitsch         PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
3389566063dSJacob Faibussowitsch         if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
3395e96ac45SJed Brown         if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3405e96ac45SJed Brown         args[j++] = tmp = DebugTerminal;
3415e96ac45SJed Brown         if (display[0]) {
3429371c9d4SSatish Balay           args[j++] = "-display";
3439371c9d4SSatish Balay           args[j++] = display;
3445e96ac45SJed Brown         }
3455e96ac45SJed Brown         while (*tmp) {
3469566063dSJacob Faibussowitsch           PetscCall(PetscStrchr(tmp, ' ', &tmp1));
3475e96ac45SJed Brown           if (!tmp1) break;
3485e96ac45SJed Brown           *tmp1     = 0;
3495e96ac45SJed Brown           tmp       = tmp1 + 1;
3505e96ac45SJed Brown           args[j++] = tmp;
3515e96ac45SJed Brown         }
3525e96ac45SJed Brown       }
353b59f628eSBarry Smith       args[j++] = PetscDebugger;
3545e96ac45SJed Brown       jj        = j;
355bf4d2887SBarry Smith       /* this is for default gdb */
356bf4d2887SBarry Smith       args[j++] = program;
357bf4d2887SBarry Smith       args[j++] = pid;
358bf4d2887SBarry Smith       args[j++] = NULL;
3595e96ac45SJed Brown 
360e5c89e4eSSatish Balay       if (isidb) {
3615e96ac45SJed Brown         j         = jj;
3625e96ac45SJed Brown         args[j++] = "-pid";
3635e96ac45SJed Brown         args[j++] = pid;
3645e96ac45SJed Brown         args[j++] = "-gdb";
3655e96ac45SJed Brown         args[j++] = program;
36602c9f0b5SLisandro Dalcin         args[j++] = NULL;
367e5c89e4eSSatish Balay       }
3680e9bae81SBarry Smith       if (islldb) {
3690e9bae81SBarry Smith         j         = jj;
3700e9bae81SBarry Smith         args[j++] = "-p";
3710e9bae81SBarry Smith         args[j++] = pid;
37202c9f0b5SLisandro Dalcin         args[j++] = NULL;
3730e9bae81SBarry Smith       }
374e5c89e4eSSatish Balay       if (isdbx) {
3755e96ac45SJed Brown         j         = jj;
3768d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3775e96ac45SJed Brown         args[j++] = "-p";
3785e96ac45SJed Brown         args[j++] = pid;
3795e96ac45SJed Brown         args[j++] = program;
380e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
3815e96ac45SJed Brown         args[j++] = "-l";
3825e96ac45SJed Brown         args[j++] = "ALL";
3835e96ac45SJed Brown         args[j++] = "-P";
3845e96ac45SJed Brown         args[j++] = pid;
3855e96ac45SJed Brown         args[j++] = program;
386e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
3875e96ac45SJed Brown         args[j++] = "-a";
3885e96ac45SJed Brown         args[j++] = pid;
389e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
3905e96ac45SJed Brown         args[j++] = "-pid";
3915e96ac45SJed Brown         args[j++] = pid;
3925e96ac45SJed Brown         args[j++] = program;
393493de400SSatish Balay #else
394493de400SSatish Balay         args[j++] = program;
395493de400SSatish Balay         args[j++] = pid;
3968d359177SBarry Smith #endif
39702c9f0b5SLisandro Dalcin         args[j++] = NULL;
398e5c89e4eSSatish Balay       }
399c823fc1fSBarry Smith       if (UseDebugTerminal) {
400c5888dd7SBarry 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);
401c5888dd7SBarry Smith         else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);
402a297a907SKarl Rupp 
4035e96ac45SJed Brown         if (execvp(args[0], (char **)args) < 0) {
4045e96ac45SJed Brown           perror("Unable to start debugger in xterm");
4055e96ac45SJed Brown           exit(0);
4065e96ac45SJed Brown         }
4075e96ac45SJed Brown       } else {
408c5888dd7SBarry Smith         printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
409e5c89e4eSSatish Balay         if (execvp(args[0], (char **)args) < 0) {
410e5c89e4eSSatish Balay           perror("Unable to start debugger");
411e5c89e4eSSatish Balay           exit(0);
412e5c89e4eSSatish Balay         }
413e5c89e4eSSatish Balay       }
414e5c89e4eSSatish Balay     }
415e5c89e4eSSatish Balay   } else {          /* I am the child, continue with user code */
416e5c89e4eSSatish Balay     sleeptime = 10; /* default to sleep waiting for debugger */
4179566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
418e5c89e4eSSatish Balay     if (sleeptime < 0) sleeptime = -sleeptime;
419e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
420e5c89e4eSSatish Balay     /*
421e5c89e4eSSatish Balay         HP cannot attach process to sleeping debugger, hence count instead
422e5c89e4eSSatish Balay     */
423e5c89e4eSSatish Balay     {
424e5c89e4eSSatish Balay       PetscReal x = 1.0;
425e5c89e4eSSatish Balay       int       i = 10000000;
426e5c89e4eSSatish Balay       while (i--) x++; /* cannot attach to sleeper */
427e5c89e4eSSatish Balay     }
428e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
429e5c89e4eSSatish Balay     /*
430e5c89e4eSSatish Balay         IBM sleep may return at anytime, hence must see if there is more time to sleep
431e5c89e4eSSatish Balay     */
432e5c89e4eSSatish Balay     {
433e5c89e4eSSatish Balay       int left = sleeptime;
434a297a907SKarl Rupp       while (left > 0) left = PetscSleep(left) - 1;
435e5c89e4eSSatish Balay     }
436e5c89e4eSSatish Balay #else
437e5c89e4eSSatish Balay     PetscSleep(sleeptime);
438e5c89e4eSSatish Balay #endif
439e5c89e4eSSatish Balay   }
440e5c89e4eSSatish Balay #endif
44111cc89d2SBarry Smith   return 0;
442e5c89e4eSSatish Balay }
443e5c89e4eSSatish Balay 
444e5c89e4eSSatish Balay /*@C
445e5c89e4eSSatish Balay    PetscAttachDebuggerErrorHandler - Error handler that attaches
446e5c89e4eSSatish Balay    a debugger to a running process when an error is detected.
447e5c89e4eSSatish Balay    This routine is useful for examining variables, etc.
448e5c89e4eSSatish Balay 
449e5c89e4eSSatish Balay    Not Collective
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay    Input Parameters:
452e32f2f54SBarry Smith +  comm - communicator over which error occurred
453e32f2f54SBarry Smith .  line - the line number of the error (indicated by __LINE__)
454e5c89e4eSSatish Balay .  file - the file in which the error was detected (indicated by __FILE__)
455e5c89e4eSSatish Balay .  message - an error text string, usually just printed to the screen
456e5c89e4eSSatish Balay .  number - the generic error number
457*811af0c4SBarry Smith .  p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
458e5c89e4eSSatish Balay -  ctx - error handler context
459e5c89e4eSSatish Balay 
460e5c89e4eSSatish Balay    Options Database Keys:
46145b666d6SBarry Smith +  -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment
46245b666d6SBarry Smith -  -start_in_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] [-debugger_ranks m,n]
463e5c89e4eSSatish Balay 
464e5c89e4eSSatish Balay    Level: developer
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay    Notes:
467c4fb7a8fSRichard Tran Mills    By default the GNU debugger, gdb, is used.  Alternatives are cuda-gdb, lldb, dbx and
468e5c89e4eSSatish Balay    xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
469e5c89e4eSSatish Balay 
470e5c89e4eSSatish Balay    Most users need not directly employ this routine and the other error
471e5c89e4eSSatish Balay    handlers, but can instead use the simplified interface SETERR, which has
472e5c89e4eSSatish Balay    the calling sequence
473e32f2f54SBarry Smith $     SETERRQ(PETSC_COMM_SELF,number,p,message)
474e5c89e4eSSatish Balay 
475e5c89e4eSSatish Balay    Notes for experienced users:
476*811af0c4SBarry Smith    Use `PetscPushErrorHandler()` to set the desired error handler.  The
477e5c89e4eSSatish Balay    currently available PETSc error handlers are
478e5c89e4eSSatish Balay $    PetscTraceBackErrorHandler()
479e5c89e4eSSatish Balay $    PetscAttachDebuggerErrorHandler()
480e5c89e4eSSatish Balay $    PetscAbortErrorHandler()
481e5c89e4eSSatish Balay    or you may write your own.
482e5c89e4eSSatish Balay 
483*811af0c4SBarry Smith    Developer Note:
484*811af0c4SBarry Smith      This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
48569412655SBarry Smith      causing the debugger to be attached again in a cycle.
48669412655SBarry Smith 
487db781477SPatrick Sanan .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
488db781477SPatrick Sanan           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
489e5c89e4eSSatish Balay @*/
4909371c9d4SSatish Balay PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx) {
491e5c89e4eSSatish Balay   if (!mess) mess = " ";
492e5c89e4eSSatish Balay 
49349c86fc7SBarry Smith   if (fun) (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
49449c86fc7SBarry Smith   else (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
495e5c89e4eSSatish Balay 
49669412655SBarry Smith   PetscAttachDebugger();
497*811af0c4SBarry Smith   abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
498*811af0c4SBarry Smith   PetscFunctionReturn(0);
499e5c89e4eSSatish Balay }
500e5c89e4eSSatish Balay 
501e5c89e4eSSatish Balay /*@C
502e5c89e4eSSatish Balay    PetscStopForDebugger - Prints a message to the screen indicating how to
503e5c89e4eSSatish Balay          attach to the process with the debugger and then waits for the
504e5c89e4eSSatish Balay          debugger to attach.
505e5c89e4eSSatish Balay 
506e5c89e4eSSatish Balay    Not Collective
507e5c89e4eSSatish Balay 
508*811af0c4SBarry Smith    Options Database Key:
5091f690a00SBarry Smith .   -stop_for_debugger - will stop for you to attach the debugger when PetscInitialize() is called
5101f690a00SBarry Smith 
5118d359177SBarry Smith    Level: developer
512e5c89e4eSSatish Balay 
513*811af0c4SBarry Smith    Note:
514*811af0c4SBarry Smith     This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
5158d359177SBarry Smith 
516*811af0c4SBarry Smith    Developer Note:
517*811af0c4SBarry Smith     Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
518f35f84d1SBarry Smith 
519db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
520e5c89e4eSSatish Balay @*/
5219371c9d4SSatish Balay PetscErrorCode PetscStopForDebugger(void) {
522e5c89e4eSSatish Balay   PetscErrorCode ierr;
523e5c89e4eSSatish Balay   PetscInt       sleeptime = 0;
524e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
52551ec2c11SGlenn Hammond   int         ppid;
526e5c89e4eSSatish Balay   PetscMPIInt rank;
527e5c89e4eSSatish Balay   char        program[PETSC_MAX_PATH_LEN], hostname[256];
5288d359177SBarry Smith   PetscBool   isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
529e5c89e4eSSatish Balay #endif
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay   PetscFunctionBegin;
532e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
533e5c89e4eSSatish Balay   (*PetscErrorPrintf)("System cannot start debugger; just continuing program\n");
534e5c89e4eSSatish Balay #else
535e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
536f35f84d1SBarry Smith   if (ierr) rank = 0; /* ignore error since this may be already in error handler */
537589a23caSBarry Smith   ierr = PetscGetHostName(hostname, sizeof(hostname));
538e5c89e4eSSatish Balay   if (ierr) {
539e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n");
540e5c89e4eSSatish Balay     PetscFunctionReturn(0);
541e5c89e4eSSatish Balay   }
542e5c89e4eSSatish Balay 
543589a23caSBarry Smith   ierr = PetscGetProgramName(program, sizeof(program));
544e5c89e4eSSatish Balay   if (ierr) {
545e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
546e5c89e4eSSatish Balay     PetscFunctionReturn(0);
547e5c89e4eSSatish Balay   }
548e5c89e4eSSatish Balay   if (!program[0]) {
549e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Cannot determine program name; just continuing program\n");
550e5c89e4eSSatish Balay     PetscFunctionReturn(0);
551e5c89e4eSSatish Balay   }
552e5c89e4eSSatish Balay 
553e5c89e4eSSatish Balay   ppid = getpid();
554e5c89e4eSSatish Balay 
5559566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
5569566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
5579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
5589566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
5599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
5609566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
5619566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
5629566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
563e5c89e4eSSatish Balay 
564c5888dd7SBarry Smith   if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
565c5888dd7SBarry Smith   else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
566c5888dd7SBarry Smith   else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
5678d359177SBarry Smith   else if (isdbx) {
568e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
569c5888dd7SBarry Smith     printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
570e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
571c5888dd7SBarry Smith     printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
572e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
573c5888dd7SBarry Smith     printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
574e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
575c5888dd7SBarry Smith     printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
576e5c89e4eSSatish Balay #else
577c5888dd7SBarry Smith     printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
578e5c89e4eSSatish Balay #endif
5798d359177SBarry Smith   }
580e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
581e5c89e4eSSatish Balay 
582f35f84d1SBarry Smith   fflush(stdout); /* ignore error because may already be in error handler */
583e5c89e4eSSatish Balay 
584e5c89e4eSSatish Balay   sleeptime = 25;                                                      /* default to sleep waiting for debugger */
585c5929fdfSBarry Smith   PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL); /* ignore error because may already be in error handler */
586e5c89e4eSSatish Balay   if (sleeptime < 0) sleeptime = -sleeptime;
587e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
588e5c89e4eSSatish Balay   /*
589e5c89e4eSSatish Balay       HP cannot attach process to sleeping debugger, hence count instead
590e5c89e4eSSatish Balay   */
591e5c89e4eSSatish Balay   {
592e5c89e4eSSatish Balay     PetscReal x = 1.0;
593e5c89e4eSSatish Balay     int       i = 10000000;
594e5c89e4eSSatish Balay     while (i--) x++; /* cannot attach to sleeper */
595e5c89e4eSSatish Balay   }
596e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
597e5c89e4eSSatish Balay   /*
598e5c89e4eSSatish Balay       IBM sleep may return at anytime, hence must see if there is more time to sleep
599e5c89e4eSSatish Balay   */
600e5c89e4eSSatish Balay   {
601e5c89e4eSSatish Balay     int left = sleeptime;
602a297a907SKarl Rupp     while (left > 0) left = sleep(left) - 1;
603e5c89e4eSSatish Balay   }
604e5c89e4eSSatish Balay #else
605e5c89e4eSSatish Balay   PetscSleep(sleeptime);
606e5c89e4eSSatish Balay #endif
607e5c89e4eSSatish Balay   PetscFunctionReturn(0);
608e5c89e4eSSatish Balay }
609