1e5c89e4eSSatish Balay /*
2e5c89e4eSSatish Balay Code to handle PETSc starting up in debuggers,etc.
3e5c89e4eSSatish Balay */
4cfbfffeaSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fileno() */
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
20cc4c1da9SBarry Smith /*@
21c823fc1fSBarry Smith PetscSetDebugTerminal - Sets the terminal to use for debugging.
225e96ac45SJed Brown
23cf53795eSBarry Smith Not Collective; No Fortran Support
245e96ac45SJed Brown
25811af0c4SBarry Smith Input Parameter:
26a2b725a8SWilliam Gropp . terminal - name of terminal and any flags required to execute a program.
27c3cd2bb4SBarry Smith For example "xterm", "urxvt -e", "gnome-terminal -x".
286e25c4a1SBarry Smith On Apple macOS you can use "Terminal" (note the capital T)
295e96ac45SJed Brown
30811af0c4SBarry Smith Options Database Key:
31c3cd2bb4SBarry 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.
376e25c4a1SBarry Smith .vb
386e25c4a1SBarry Smith mpiexec -n 4 ./myapp -start_in_debugger -debug_terminal "screen -X -S debug screen"
396e25c4a1SBarry Smith .ve
405e96ac45SJed Brown
415e96ac45SJed Brown will open 4 windows in the session named "debug".
425e96ac45SJed Brown
436e25c4a1SBarry Smith The default terminal on Apple is Terminal, on other systems the default is xterm
44c823fc1fSBarry Smith
45c3cd2bb4SBarry Smith .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
465e96ac45SJed Brown @*/
PetscSetDebugTerminal(const char terminal[])47d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetDebugTerminal(const char terminal[])
48d71ae5a4SJacob Faibussowitsch {
49c823fc1fSBarry Smith PetscBool xterm;
505e96ac45SJed Brown
515e96ac45SJed Brown PetscFunctionBegin;
529566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(DebugTerminal, terminal, sizeof(DebugTerminal)));
539566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(terminal, "xterm", &xterm));
549566063dSJacob Faibussowitsch if (xterm) PetscCall(PetscStrlcat(DebugTerminal, " -e", sizeof(DebugTerminal)));
553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
565e96ac45SJed Brown }
575e96ac45SJed Brown
58cc4c1da9SBarry Smith /*@
59e5c89e4eSSatish Balay PetscSetDebugger - Sets options associated with the debugger.
60e5c89e4eSSatish Balay
61cf53795eSBarry Smith Not Collective; No Fortran Support
62e5c89e4eSSatish Balay
63e5c89e4eSSatish Balay Input Parameters:
64e5c89e4eSSatish Balay + debugger - name of debugger, which should be in your path,
65c4fb7a8fSRichard Tran Mills usually "lldb", "dbx", "gdb", "cuda-gdb", "idb", "xxgdb", "kdgb" or "ddd". Also, HP-UX
66e5c89e4eSSatish Balay supports "xdb", and IBM rs6000 supports "xldb".
67e5c89e4eSSatish Balay
686e25c4a1SBarry Smith - usedebugterminal - flag to indicate debugger window, set to either `PETSC_TRUE` (to indicate
696e25c4a1SBarry Smith debugger should be started in a new terminal window) or `PETSC_FALSE` (to start debugger
706e25c4a1SBarry Smith in initial window (the option `PETSC_FALSE` makes no sense when using more
718d359177SBarry Smith than one MPI process.)
72e5c89e4eSSatish Balay
73e5c89e4eSSatish Balay Level: developer
74e5c89e4eSSatish Balay
75db781477SPatrick Sanan .seealso: `PetscAttachDebugger()`, `PetscAttachDebuggerErrorHandler()`, `PetscSetDebugTerminal()`
76e5c89e4eSSatish Balay @*/
PetscSetDebugger(const char debugger[],PetscBool usedebugterminal)77d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetDebugger(const char debugger[], PetscBool usedebugterminal)
78d71ae5a4SJacob Faibussowitsch {
79e5c89e4eSSatish Balay PetscFunctionBegin;
809566063dSJacob Faibussowitsch if (debugger) PetscCall(PetscStrncpy(PetscDebugger, debugger, sizeof(PetscDebugger)));
81c823fc1fSBarry Smith if (UseDebugTerminal) UseDebugTerminal = usedebugterminal;
823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
83e5c89e4eSSatish Balay }
84e5c89e4eSSatish Balay
855d83a8b1SBarry Smith /*@
86c823fc1fSBarry Smith PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal
87e5c89e4eSSatish Balay
88cc4c1da9SBarry Smith Not Collective, No Fortran Support
89e5c89e4eSSatish Balay
908d359177SBarry Smith Level: developer
91e5c89e4eSSatish Balay
92c3cd2bb4SBarry Smith .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()`
93e5c89e4eSSatish Balay @*/
PetscSetDefaultDebugger(void)94d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscSetDefaultDebugger(void)
95d71ae5a4SJacob Faibussowitsch {
96e5c89e4eSSatish Balay PetscFunctionBegin;
974211eb48SBarry Smith #if defined(PETSC_USE_DEBUGGER)
989566063dSJacob Faibussowitsch PetscCall(PetscSetDebugger(PETSC_USE_DEBUGGER, PETSC_TRUE));
99e5c89e4eSSatish Balay #endif
100c823fc1fSBarry Smith #if defined(__APPLE__)
1019566063dSJacob Faibussowitsch PetscCall(PetscSetDebugTerminal("Terminal"));
102c823fc1fSBarry Smith #else
1039566063dSJacob Faibussowitsch PetscCall(PetscSetDebugTerminal("xterm"));
104c823fc1fSBarry Smith #endif
1053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
106e5c89e4eSSatish Balay }
107e5c89e4eSSatish Balay
PetscCheckDebugger_Private(const char defaultDbg[],const char string[],const char * debugger[])108d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscCheckDebugger_Private(const char defaultDbg[], const char string[], const char *debugger[])
109d71ae5a4SJacob Faibussowitsch {
110bbcf679cSJacob Faibussowitsch char *f = NULL;
111e5c89e4eSSatish Balay
112e5c89e4eSSatish Balay PetscFunctionBegin;
1139566063dSJacob Faibussowitsch PetscCall(PetscStrstr(string, defaultDbg, &f));
114e5c89e4eSSatish Balay if (f) {
115bbcf679cSJacob Faibussowitsch PetscBool exists;
116bbcf679cSJacob Faibussowitsch
1179566063dSJacob Faibussowitsch PetscCall(PetscTestFile(string, 'x', &exists));
118a297a907SKarl Rupp if (exists) *debugger = string;
119a297a907SKarl Rupp else *debugger = defaultDbg;
120e5c89e4eSSatish Balay }
1213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
122e5c89e4eSSatish Balay }
123e5c89e4eSSatish Balay
124cc4c1da9SBarry Smith /*@
125e5c89e4eSSatish Balay PetscSetDebuggerFromString - Set the complete path for the
126e5c89e4eSSatish Balay debugger for PETSc to use.
127e5c89e4eSSatish Balay
12820f4b53cSBarry Smith Not Collective
129e5c89e4eSSatish Balay
13010450e9eSJacob Faibussowitsch Input Parameter:
13110450e9eSJacob Faibussowitsch . string - the name of the debugger, for example "gdb"
13210450e9eSJacob Faibussowitsch
1337c764164SBarry Smith Level: developer
134e5c89e4eSSatish Balay
135c3cd2bb4SBarry Smith .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscAttachDebugger()`
136e5c89e4eSSatish Balay @*/
PetscSetDebuggerFromString(const char string[])137cc4c1da9SBarry Smith PetscErrorCode PetscSetDebuggerFromString(const char string[])
138d71ae5a4SJacob Faibussowitsch {
1390298fd71SBarry Smith const char *debugger = NULL;
140c823fc1fSBarry Smith PetscBool useterminal = PETSC_TRUE;
141bbcf679cSJacob Faibussowitsch char *f = NULL;
142e5c89e4eSSatish Balay
143e5c89e4eSSatish Balay PetscFunctionBegin;
1449566063dSJacob Faibussowitsch PetscCall(PetscStrstr(string, "noxterm", &f));
145c823fc1fSBarry Smith if (f) useterminal = PETSC_FALSE;
1469566063dSJacob Faibussowitsch PetscCall(PetscStrstr(string, "ddd", &f));
147c823fc1fSBarry Smith if (f) useterminal = PETSC_FALSE;
1489566063dSJacob Faibussowitsch PetscCall(PetscStrstr(string, "noterminal", &f));
149c823fc1fSBarry Smith if (f) useterminal = PETSC_FALSE;
1509566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("xdb", string, &debugger));
1519566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("dbx", string, &debugger));
1529566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("xldb", string, &debugger));
1539566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("gdb", string, &debugger));
1549566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("cuda-gdb", string, &debugger));
1559566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("idb", string, &debugger));
1569566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("xxgdb", string, &debugger));
1579566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("ddd", string, &debugger));
1589566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("kdbg", string, &debugger));
1599566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("ups", string, &debugger));
1609566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("workshop", string, &debugger));
1619566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("pgdbg", string, &debugger));
1629566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("pathdb", string, &debugger));
1639566063dSJacob Faibussowitsch PetscCall(PetscCheckDebugger_Private("lldb", string, &debugger));
1649566063dSJacob Faibussowitsch PetscCall(PetscSetDebugger(debugger, useterminal));
1653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
166e5c89e4eSSatish Balay }
167e5c89e4eSSatish Balay
1682a2a2941SBarry Smith /*@
169811af0c4SBarry Smith PetscWaitOnError - If an error is detected and the process would normally exit the main program with `MPI_Abort()` sleep instead
1702a2a2941SBarry Smith of exiting.
1712a2a2941SBarry Smith
1722a2a2941SBarry Smith Not Collective
1732a2a2941SBarry Smith
1742a2a2941SBarry Smith Level: advanced
1752a2a2941SBarry Smith
176811af0c4SBarry Smith Note:
177c3cd2bb4SBarry 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
1782a2a2941SBarry Smith killing the user's debugging sessions.
1792a2a2941SBarry Smith
180db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
1812a2a2941SBarry Smith @*/
PetscWaitOnError(void)1823274405dSPierre Jolivet PetscErrorCode PetscWaitOnError(void)
183d71ae5a4SJacob Faibussowitsch {
184baae8e41SSatish Balay petscwaitonerrorflg = PETSC_TRUE;
1853ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
1862a2a2941SBarry Smith }
187e5c89e4eSSatish Balay
188e30d2299SSatish Balay /*@
189e5c89e4eSSatish Balay PetscAttachDebugger - Attaches the debugger to the running process.
190e5c89e4eSSatish Balay
191e5c89e4eSSatish Balay Not Collective
192e5c89e4eSSatish Balay
1931f690a00SBarry Smith Options Database Keys:
1940b4b7b1cSBarry Smith + -start_in_debugger [noxterm,lldb or gdb] - Set debugger debug_terminal xterm or Terminal (for Apple)
1950b4b7b1cSBarry Smith . -display name - XDisplay to open xterm in
1960b4b7b1cSBarry Smith . -debugger_ranks m,n - Which MPI ranks on which to start the debugger, defaults to all
1970b4b7b1cSBarry Smith . -stop_for_debugger - Print a message on how to attach the process with a debugger and then wait for the user to attach
1980b4b7b1cSBarry Smith - -debugger_pause <secs> - Wait <secs> before attaching the debugger. This is useful for slow connections
1990b4b7b1cSBarry Smith that take a long time for the Terminal window or xterm to start up.
2001f690a00SBarry Smith
201e5c89e4eSSatish Balay Level: advanced
202e5c89e4eSSatish Balay
203c3cd2bb4SBarry Smith Note:
2040b4b7b1cSBarry Smith If you get the message "`stdin` is not a `tty`, hence unable to attach debugger, see `PetscAttachDebugger()`", this means the application
205c3cd2bb4SBarry Smith is likely running in a batch system and you do not have terminal access to the process. You can try
206c3cd2bb4SBarry Smith running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger`
207c3cd2bb4SBarry Smith
2086e25c4a1SBarry Smith Developer Note:
209c3cd2bb4SBarry Smith Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
210f35f84d1SBarry Smith
211db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()`
212e5c89e4eSSatish Balay @*/
PetscAttachDebugger(void)213d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscAttachDebugger(void)
214d71ae5a4SJacob Faibussowitsch {
2153ba16761SJacob Faibussowitsch PetscErrorCode PETSC_UNUSED ierr;
216ed50d614Sprj- #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK)
217e5c89e4eSSatish Balay int child = 0;
218a6d0e24fSJed Brown PetscReal sleeptime = 0;
219e5c89e4eSSatish Balay char program[PETSC_MAX_PATH_LEN], display[256], hostname[64];
220e5c89e4eSSatish Balay #endif
221e5c89e4eSSatish Balay
222e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK)
2233ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("System cannot start debugger\n");
2243ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n");
2253ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n");
22641e02c4dSJunchao Zhang PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS);
227e5c89e4eSSatish Balay #else
22863a3b9bcSJacob Faibussowitsch if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) {
229cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n");
23011cc89d2SBarry Smith return PETSC_ERR_SYS;
2315f80ce2aSJacob Faibussowitsch }
23263a3b9bcSJacob Faibussowitsch if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) {
233cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
23411cc89d2SBarry Smith return PETSC_ERR_SYS;
235e5c89e4eSSatish Balay }
2365f80ce2aSJacob Faibussowitsch if (PetscUnlikely(!program[0])) {
237cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n");
238cfbfffeaSBarry Smith return PETSC_ERR_SYS;
239cfbfffeaSBarry Smith }
240ac530a7eSPierre Jolivet if (PetscUnlikely(!isatty(fileno(stdin))) && !UseDebugTerminal) printf("If the debugger exits immediately or hangs, this indicates you cannot use PetscAttachDebugger() in this situation\n\n");
241835f2295SStefano Zampini child = fork();
2425f80ce2aSJacob Faibussowitsch if (PetscUnlikely(child < 0)) {
243cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n");
24411cc89d2SBarry Smith return PETSC_ERR_SYS;
245e5c89e4eSSatish Balay }
246bf4d2887SBarry Smith petscindebugger = PETSC_TRUE;
247e5c89e4eSSatish Balay
248e5c89e4eSSatish Balay /*
249e5c89e4eSSatish Balay Swap role the parent and child. This is (I think) so that control c typed
250e5c89e4eSSatish Balay in the debugger goes to the correct process.
251e5c89e4eSSatish Balay */
252234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER)
253835f2295SStefano Zampini child = child ? 0 : getppid();
254234acd79SBarry Smith #endif
255e5c89e4eSSatish Balay
256e5c89e4eSSatish Balay if (child) { /* I am the parent, will run the debugger */
257e5c89e4eSSatish Balay const char *args[10];
258e5c89e4eSSatish Balay char pid[10];
2595e96ac45SJed Brown PetscInt j, jj;
2600e9bae81SBarry Smith PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb;
261e5c89e4eSSatish Balay
2629566063dSJacob Faibussowitsch PetscCall(PetscGetHostName(hostname, sizeof(hostname)));
263e5c89e4eSSatish Balay /*
264e5c89e4eSSatish Balay We need to send a continue signal to the "child" process on the
265e5c89e4eSSatish Balay alpha, otherwise it just stays off forever
266e5c89e4eSSatish Balay */
267e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER)
268e5c89e4eSSatish Balay kill(child, SIGCONT);
269e5c89e4eSSatish Balay #endif
270a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child));
271e5c89e4eSSatish Balay
2729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
2739566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
2749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
2759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
2769566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
2779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
2789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
2799566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb));
2809566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop));
2819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
282e5c89e4eSSatish Balay
283e5c89e4eSSatish Balay if (isxxgdb || isups || isddd) {
2849371c9d4SSatish Balay args[1] = program;
2859371c9d4SSatish Balay args[2] = pid;
2869371c9d4SSatish Balay args[3] = "-display";
2879371c9d4SSatish Balay args[0] = PetscDebugger;
2889371c9d4SSatish Balay args[4] = display;
2899371c9d4SSatish Balay args[5] = NULL;
290c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
291e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) {
292e5c89e4eSSatish Balay perror("Unable to start debugger");
293e5c89e4eSSatish Balay exit(0);
294e5c89e4eSSatish Balay }
295bf902449SSatish Balay } else if (iskdbg) {
2969371c9d4SSatish Balay args[1] = "-p";
2979371c9d4SSatish Balay args[2] = pid;
2989371c9d4SSatish Balay args[3] = program;
2999371c9d4SSatish Balay args[4] = "-display";
3009371c9d4SSatish Balay args[0] = PetscDebugger;
3019371c9d4SSatish Balay args[5] = display;
3029371c9d4SSatish Balay args[6] = NULL;
303c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname);
304bf902449SSatish Balay if (execvp(args[0], (char **)args) < 0) {
305bf902449SSatish Balay perror("Unable to start debugger");
306bf902449SSatish Balay exit(0);
307bf902449SSatish Balay }
308e5c89e4eSSatish Balay } else if (isxldb) {
3099371c9d4SSatish Balay args[1] = "-a";
3109371c9d4SSatish Balay args[2] = pid;
3119371c9d4SSatish Balay args[3] = program;
3129371c9d4SSatish Balay args[4] = "-display";
3139371c9d4SSatish Balay args[0] = PetscDebugger;
3149371c9d4SSatish Balay args[5] = display;
3159371c9d4SSatish Balay args[6] = NULL;
316c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname);
317e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) {
318e5c89e4eSSatish Balay perror("Unable to start debugger");
319e5c89e4eSSatish Balay exit(0);
320e5c89e4eSSatish Balay }
321e5c89e4eSSatish Balay } else if (isworkshop) {
3229371c9d4SSatish Balay args[1] = "-s";
3239371c9d4SSatish Balay args[2] = pid;
3249371c9d4SSatish Balay args[3] = "-D";
3259371c9d4SSatish Balay args[4] = "-";
3269371c9d4SSatish Balay args[0] = PetscDebugger;
3279371c9d4SSatish Balay args[5] = pid;
3289371c9d4SSatish Balay args[6] = "-display";
3299371c9d4SSatish Balay args[7] = display;
3309371c9d4SSatish Balay args[8] = NULL;
331c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname);
332e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) {
333e5c89e4eSSatish Balay perror("Unable to start debugger");
334e5c89e4eSSatish Balay exit(0);
335e5c89e4eSSatish Balay }
3365e96ac45SJed Brown } else {
3375e96ac45SJed Brown j = 0;
338c823fc1fSBarry Smith if (UseDebugTerminal) {
339ace3abfcSBarry Smith PetscBool cmp;
340bbcf679cSJacob Faibussowitsch char *tmp, *tmp1 = NULL;
3419566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp));
342c823fc1fSBarry Smith if (cmp) {
343c823fc1fSBarry Smith char command[1024];
3449483a8a2SBarry Smith if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid));
3459483a8a2SBarry Smith else {
3469483a8a2SBarry Smith char fullprogram[PETSC_MAX_PATH_LEN];
3479483a8a2SBarry Smith PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram)));
3489483a8a2SBarry Smith PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid));
3499483a8a2SBarry Smith }
350accbd18bSBarry Smith #if defined(PETSC_HAVE_POPEN)
3519566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL));
352accbd18bSBarry Smith #else
353accbd18bSBarry Smith printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n");
354accbd18bSBarry Smith #endif
355c823fc1fSBarry Smith exit(0);
356c823fc1fSBarry Smith }
357c823fc1fSBarry Smith
3589566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp));
3599566063dSJacob Faibussowitsch if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp));
3605e96ac45SJed Brown if (cmp) display[0] = 0; /* when using screen, we never pass -display */
3615e96ac45SJed Brown args[j++] = tmp = DebugTerminal;
3625e96ac45SJed Brown if (display[0]) {
3639371c9d4SSatish Balay args[j++] = "-display";
3649371c9d4SSatish Balay args[j++] = display;
3655e96ac45SJed Brown }
3665e96ac45SJed Brown while (*tmp) {
3679566063dSJacob Faibussowitsch PetscCall(PetscStrchr(tmp, ' ', &tmp1));
3685e96ac45SJed Brown if (!tmp1) break;
3695e96ac45SJed Brown *tmp1 = 0;
3705e96ac45SJed Brown tmp = tmp1 + 1;
3715e96ac45SJed Brown args[j++] = tmp;
3725e96ac45SJed Brown }
3735e96ac45SJed Brown }
374b59f628eSBarry Smith args[j++] = PetscDebugger;
3755e96ac45SJed Brown jj = j;
376bf4d2887SBarry Smith /* this is for default gdb */
377bf4d2887SBarry Smith args[j++] = program;
378bf4d2887SBarry Smith args[j++] = pid;
379bf4d2887SBarry Smith args[j++] = NULL;
3805e96ac45SJed Brown
381e5c89e4eSSatish Balay if (isidb) {
3825e96ac45SJed Brown j = jj;
3835e96ac45SJed Brown args[j++] = "-pid";
3845e96ac45SJed Brown args[j++] = pid;
3855e96ac45SJed Brown args[j++] = "-gdb";
3865e96ac45SJed Brown args[j++] = program;
38702c9f0b5SLisandro Dalcin args[j++] = NULL;
388e5c89e4eSSatish Balay }
3890e9bae81SBarry Smith if (islldb) {
3900e9bae81SBarry Smith j = jj;
3910e9bae81SBarry Smith args[j++] = "-p";
3920e9bae81SBarry Smith args[j++] = pid;
39302c9f0b5SLisandro Dalcin args[j++] = NULL;
3940e9bae81SBarry Smith }
395e5c89e4eSSatish Balay if (isdbx) {
3965e96ac45SJed Brown j = jj;
3978d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER)
3985e96ac45SJed Brown args[j++] = "-p";
3995e96ac45SJed Brown args[j++] = pid;
4005e96ac45SJed Brown args[j++] = program;
401e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
4025e96ac45SJed Brown args[j++] = "-l";
4035e96ac45SJed Brown args[j++] = "ALL";
4045e96ac45SJed Brown args[j++] = "-P";
4055e96ac45SJed Brown args[j++] = pid;
4065e96ac45SJed Brown args[j++] = program;
407e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
4085e96ac45SJed Brown args[j++] = "-a";
4095e96ac45SJed Brown args[j++] = pid;
410e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
4115e96ac45SJed Brown args[j++] = "-pid";
4125e96ac45SJed Brown args[j++] = pid;
4135e96ac45SJed Brown args[j++] = program;
414493de400SSatish Balay #else
415493de400SSatish Balay args[j++] = program;
416493de400SSatish Balay args[j++] = pid;
4178d359177SBarry Smith #endif
41802c9f0b5SLisandro Dalcin args[j++] = NULL;
419e5c89e4eSSatish Balay }
420c823fc1fSBarry Smith if (UseDebugTerminal) {
421c5888dd7SBarry 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);
422c5888dd7SBarry Smith else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname);
423a297a907SKarl Rupp
4245e96ac45SJed Brown if (execvp(args[0], (char **)args) < 0) {
4255e96ac45SJed Brown perror("Unable to start debugger in xterm");
4265e96ac45SJed Brown exit(0);
4275e96ac45SJed Brown }
4285e96ac45SJed Brown } else {
429c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname);
430e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) {
431e5c89e4eSSatish Balay perror("Unable to start debugger");
432e5c89e4eSSatish Balay exit(0);
433e5c89e4eSSatish Balay }
434e5c89e4eSSatish Balay }
435e5c89e4eSSatish Balay }
436e5c89e4eSSatish Balay } else { /* I am the child, continue with user code */
437e5c89e4eSSatish Balay sleeptime = 10; /* default to sleep waiting for debugger */
4389566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL));
439e5c89e4eSSatish Balay if (sleeptime < 0) sleeptime = -sleeptime;
440e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
441e5c89e4eSSatish Balay /*
442e5c89e4eSSatish Balay HP cannot attach process to sleeping debugger, hence count instead
443e5c89e4eSSatish Balay */
444e5c89e4eSSatish Balay {
445e5c89e4eSSatish Balay PetscReal x = 1.0;
446e5c89e4eSSatish Balay int i = 10000000;
447e5c89e4eSSatish Balay while (i--) x++; /* cannot attach to sleeper */
448e5c89e4eSSatish Balay }
449e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
450e5c89e4eSSatish Balay /*
451e5c89e4eSSatish Balay IBM sleep may return at anytime, hence must see if there is more time to sleep
452e5c89e4eSSatish Balay */
453e5c89e4eSSatish Balay {
454e5c89e4eSSatish Balay int left = sleeptime;
455a297a907SKarl Rupp while (left > 0) left = PetscSleep(left) - 1;
456e5c89e4eSSatish Balay }
457e5c89e4eSSatish Balay #else
4583ba16761SJacob Faibussowitsch PetscCall(PetscSleep(sleeptime));
459e5c89e4eSSatish Balay #endif
460e5c89e4eSSatish Balay }
461e5c89e4eSSatish Balay #endif
4623ba16761SJacob Faibussowitsch return PETSC_SUCCESS;
463e5c89e4eSSatish Balay }
464e5c89e4eSSatish Balay
465e5c89e4eSSatish Balay /*@C
466e5c89e4eSSatish Balay PetscAttachDebuggerErrorHandler - Error handler that attaches
467e5c89e4eSSatish Balay a debugger to a running process when an error is detected.
468e5c89e4eSSatish Balay This routine is useful for examining variables, etc.
469e5c89e4eSSatish Balay
470cc4c1da9SBarry Smith Not Collective, No Fortran Support
471e5c89e4eSSatish Balay
472e5c89e4eSSatish Balay Input Parameters:
473e32f2f54SBarry Smith + comm - communicator over which error occurred
4746e25c4a1SBarry Smith . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
4756e25c4a1SBarry Smith . fun - the function name of the calling routine
4766e25c4a1SBarry Smith . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
47710450e9eSJacob Faibussowitsch . mess - an error text string, usually just printed to the screen
47810450e9eSJacob Faibussowitsch . num - the generic error number
479811af0c4SBarry Smith . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
480e5c89e4eSSatish Balay - ctx - error handler context
481e5c89e4eSSatish Balay
482e5c89e4eSSatish Balay Level: developer
483e5c89e4eSSatish Balay
484e5c89e4eSSatish Balay Notes:
4856e25c4a1SBarry Smith By default the GNU debugger, gdb, is used except on macOS where lldb is used. Alternatives are cuda-gdb, lldb, dbx and
486e5c89e4eSSatish Balay xxgdb,xldb (on IBM rs6000), xdb (on HP-UX).
487e5c89e4eSSatish Balay
488e5c89e4eSSatish Balay Most users need not directly employ this routine and the other error
489e5c89e4eSSatish Balay handlers, but can instead use the simplified interface SETERR, which has
490e5c89e4eSSatish Balay the calling sequence
4916e25c4a1SBarry Smith .vb
4926e25c4a1SBarry Smith SETERRQ(PETSC_COMM_SELF, number, p, message)
4936e25c4a1SBarry Smith .ve
494e5c89e4eSSatish Balay
495811af0c4SBarry Smith Use `PetscPushErrorHandler()` to set the desired error handler. The
496e5c89e4eSSatish Balay currently available PETSc error handlers are
49720f4b53cSBarry Smith .vb
49820f4b53cSBarry Smith PetscTraceBackErrorHandler()
49920f4b53cSBarry Smith PetscAttachDebuggerErrorHandler()
50020f4b53cSBarry Smith PetscAbortErrorHandler()
50120f4b53cSBarry Smith .ve
502e5c89e4eSSatish Balay or you may write your own.
503e5c89e4eSSatish Balay
5046e25c4a1SBarry Smith Developer Note:
505811af0c4SBarry Smith This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception
50669412655SBarry Smith causing the debugger to be attached again in a cycle.
50769412655SBarry Smith
508db781477SPatrick Sanan .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`,
509db781477SPatrick Sanan `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()`
510e5c89e4eSSatish Balay @*/
PetscAttachDebuggerErrorHandler(MPI_Comm comm,int line,const char * fun,const char * file,PetscErrorCode num,PetscErrorType p,const char * mess,PetscCtx ctx)511*2a8381b2SBarry Smith PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, PetscCtx ctx)
512d71ae5a4SJacob Faibussowitsch {
51310450e9eSJacob Faibussowitsch (void)comm;
51410450e9eSJacob Faibussowitsch (void)num;
51510450e9eSJacob Faibussowitsch (void)p;
51610450e9eSJacob Faibussowitsch (void)ctx;
517e5c89e4eSSatish Balay if (!mess) mess = " ";
518e5c89e4eSSatish Balay
519dd460d27SBarry Smith if (fun) (void)(*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess);
520dd460d27SBarry Smith else (void)(*PetscErrorPrintf)("%s:%d %s\n", file, line, mess);
521e5c89e4eSSatish Balay
522dd460d27SBarry Smith (void)PetscAttachDebugger();
523811af0c4SBarry Smith abort(); /* call abort because don't want to kill other MPI ranks that may successfully attach to debugger */
5243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
525e5c89e4eSSatish Balay }
526e5c89e4eSSatish Balay
5275d83a8b1SBarry Smith /*@
528e5c89e4eSSatish Balay PetscStopForDebugger - Prints a message to the screen indicating how to
529e5c89e4eSSatish Balay attach to the process with the debugger and then waits for the
530e5c89e4eSSatish Balay debugger to attach.
531e5c89e4eSSatish Balay
532cc4c1da9SBarry Smith Not Collective, No Fortran Support
533e5c89e4eSSatish Balay
534811af0c4SBarry Smith Options Database Key:
5356e25c4a1SBarry Smith . -stop_for_debugger - will stop for you to attach the debugger when `PetscInitialize()` is called
5361f690a00SBarry Smith
5378d359177SBarry Smith Level: developer
538e5c89e4eSSatish Balay
539811af0c4SBarry Smith Note:
540811af0c4SBarry Smith This is likely never needed since `PetscAttachDebugger()` is easier to use and seems to always work.
5418d359177SBarry Smith
5426e25c4a1SBarry Smith Developer Note:
543811af0c4SBarry Smith Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`?
544f35f84d1SBarry Smith
545db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscAttachDebugger()`
546e5c89e4eSSatish Balay @*/
PetscStopForDebugger(void)547d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscStopForDebugger(void)
548d71ae5a4SJacob Faibussowitsch {
549e5c89e4eSSatish Balay PetscErrorCode ierr;
550e5c89e4eSSatish Balay PetscInt sleeptime = 0;
551e5c89e4eSSatish Balay #if !defined(PETSC_CANNOT_START_DEBUGGER)
55251ec2c11SGlenn Hammond int ppid;
553e5c89e4eSSatish Balay PetscMPIInt rank;
554e5c89e4eSSatish Balay char program[PETSC_MAX_PATH_LEN], hostname[256];
5558d359177SBarry Smith PetscBool isdbx, isxldb, isxxgdb, isddd, iskdbg, isups, isxdb, islldb;
556e5c89e4eSSatish Balay #endif
557e5c89e4eSSatish Balay
558e5c89e4eSSatish Balay PetscFunctionBegin;
559e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER)
5603ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("System cannot start debugger; just continuing program\n"));
561e5c89e4eSSatish Balay #else
5623ba16761SJacob Faibussowitsch if (MPI_Comm_rank(PETSC_COMM_WORLD, &rank)) rank = 0; /* ignore error since this may be already in error handler */
563589a23caSBarry Smith ierr = PetscGetHostName(hostname, sizeof(hostname));
564e5c89e4eSSatish Balay if (ierr) {
5653ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Cannot determine hostname; just continuing program\n"));
5663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
567e5c89e4eSSatish Balay }
568e5c89e4eSSatish Balay
569589a23caSBarry Smith ierr = PetscGetProgramName(program, sizeof(program));
570e5c89e4eSSatish Balay if (ierr) {
5713ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
5723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
573e5c89e4eSSatish Balay }
574e5c89e4eSSatish Balay if (!program[0]) {
5753ba16761SJacob Faibussowitsch PetscCall((*PetscErrorPrintf)("Cannot determine program name; just continuing program\n"));
5763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
577e5c89e4eSSatish Balay }
578e5c89e4eSSatish Balay
579e5c89e4eSSatish Balay ppid = getpid();
580e5c89e4eSSatish Balay
5819566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb));
5829566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd));
5839566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg));
5849566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups));
5859566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb));
5869566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb));
5879566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx));
5889566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb));
589e5c89e4eSSatish Balay
590c5888dd7SBarry Smith if (isxxgdb || isups || isddd || iskdbg) printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
591c5888dd7SBarry Smith else if (isxldb) printf("[%d]%s>>%s -a %d %s\n", rank, hostname, PetscDebugger, ppid, program);
592c5888dd7SBarry Smith else if (islldb) printf("[%d]%s>>%s -p %d\n", rank, hostname, PetscDebugger, ppid);
5938d359177SBarry Smith else if (isdbx) {
594e5c89e4eSSatish Balay #if defined(PETSC_USE_P_FOR_DEBUGGER)
595c5888dd7SBarry Smith printf("[%d]%s>>%s -p %d %s\n", rank, hostname, PetscDebugger, ppid, program);
596e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER)
597c5888dd7SBarry Smith printf("[%d]%s>>%s -l ALL -P %d %s\n", rank, hostname, PetscDebugger, ppid, program);
598e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER)
599c5888dd7SBarry Smith printf("[%d]%s>>%s -a %d\n", rank, hostname, PetscDebugger, ppid);
600e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER)
601c5888dd7SBarry Smith printf("[%d]%s>>%s -pid %d %s\n", rank, hostname, PetscDebugger, ppid, program);
602e5c89e4eSSatish Balay #else
603c5888dd7SBarry Smith printf("[%d]%s>>%s %s %d\n", rank, hostname, PetscDebugger, program, ppid);
604e5c89e4eSSatish Balay #endif
6058d359177SBarry Smith }
606e5c89e4eSSatish Balay #endif /* PETSC_CANNOT_START_DEBUGGER */
607e5c89e4eSSatish Balay
608f35f84d1SBarry Smith fflush(stdout); /* ignore error because may already be in error handler */
609e5c89e4eSSatish Balay
610e5c89e4eSSatish Balay sleeptime = 25; /* default to sleep waiting for debugger */
6113ba16761SJacob Faibussowitsch PetscCallContinue(PetscOptionsGetInt(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); /* ignore error because may already be in error handler */
612e5c89e4eSSatish Balay if (sleeptime < 0) sleeptime = -sleeptime;
613e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP)
614e5c89e4eSSatish Balay /*
615e5c89e4eSSatish Balay HP cannot attach process to sleeping debugger, hence count instead
616e5c89e4eSSatish Balay */
617e5c89e4eSSatish Balay {
6183ba16761SJacob Faibussowitsch // this *will* get optimized away by any compiler known to man
619e5c89e4eSSatish Balay PetscReal x = 1.0;
620e5c89e4eSSatish Balay int i = 10000000;
621e5c89e4eSSatish Balay while (i--) x++; /* cannot attach to sleeper */
622e5c89e4eSSatish Balay }
623e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY)
624e5c89e4eSSatish Balay /*
625e5c89e4eSSatish Balay IBM sleep may return at anytime, hence must see if there is more time to sleep
626e5c89e4eSSatish Balay */
627e5c89e4eSSatish Balay {
628e5c89e4eSSatish Balay int left = sleeptime;
629a297a907SKarl Rupp while (left > 0) left = sleep(left) - 1;
630e5c89e4eSSatish Balay }
631e5c89e4eSSatish Balay #else
6323ba16761SJacob Faibussowitsch PetscCall(PetscSleep(sleeptime));
633e5c89e4eSSatish Balay #endif
6343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
635e5c89e4eSSatish Balay }
636