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