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 20*cc4c1da9SBarry 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 @*/ 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 58*cc4c1da9SBarry 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 @*/ 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 858d359177SBarry Smith /*@C 86c823fc1fSBarry Smith PetscSetDefaultDebugger - Causes PETSc to use its default debugger and output terminal 87e5c89e4eSSatish Balay 88*cc4c1da9SBarry Smith Not Collective, No Fortran Support 89e5c89e4eSSatish Balay 908d359177SBarry Smith Level: developer 91e5c89e4eSSatish Balay 92c3cd2bb4SBarry Smith .seealso: `PetscSetDebugger()`, `PetscSetDebuggerFromString()`, `PetscAttachDebugger()` 93e5c89e4eSSatish Balay @*/ 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 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 124*cc4c1da9SBarry 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 @*/ 137*cc4c1da9SBarry 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 @*/ 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: 1946e25c4a1SBarry Smith + -start_in_debugger [noxterm,lldb or gdb] [-display name] [-debugger_ranks m,n] - set debugger debug_terminal xterm or Terminal (for Apple) 1951f690a00SBarry Smith . -on_error_attach_debugger [noxterm,dbx,xxgdb,xdb,xldb,gdb] [-display name] - Activates debugger attachment 196c3cd2bb4SBarry Smith - -stop_for_debugger - print a message on how to attach the process with a debugger and then wait for the user to attach 1971f690a00SBarry Smith 198e5c89e4eSSatish Balay Level: advanced 199e5c89e4eSSatish Balay 200c3cd2bb4SBarry Smith Note: 201c3cd2bb4SBarry Smith If you get the message " stdin is not a tty, hence unable to attach debugger, see PetscAttachDebugger()", this means the application 202c3cd2bb4SBarry Smith is likely running in a batch system and you do not have terminal access to the process. You can try 203c3cd2bb4SBarry Smith running with `-start_in_debugger` without the `noxterm` argument or `-stop_for_debugger` 204c3cd2bb4SBarry Smith 2056e25c4a1SBarry Smith Developer Note: 206c3cd2bb4SBarry Smith Since this can be called by the error handler, should it be calling `SETERRQ()` and `PetscCall()`? 207f35f84d1SBarry Smith 208db781477SPatrick Sanan .seealso: `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscSetDebugTerminal()`, `PetscAttachDebuggerErrorHandler()`, `PetscStopForDebugger()` 209e5c89e4eSSatish Balay @*/ 210d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscAttachDebugger(void) 211d71ae5a4SJacob Faibussowitsch { 2123ba16761SJacob Faibussowitsch PetscErrorCode PETSC_UNUSED ierr; 213ed50d614Sprj- #if !defined(PETSC_CANNOT_START_DEBUGGER) && defined(PETSC_HAVE_FORK) 214e5c89e4eSSatish Balay int child = 0; 215a6d0e24fSJed Brown PetscReal sleeptime = 0; 216e5c89e4eSSatish Balay char program[PETSC_MAX_PATH_LEN], display[256], hostname[64]; 217e5c89e4eSSatish Balay #endif 218e5c89e4eSSatish Balay 219e5c89e4eSSatish Balay #if defined(PETSC_CANNOT_START_DEBUGGER) || !defined(PETSC_HAVE_FORK) 2203ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("System cannot start debugger\n"); 2213ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("On Cray run program in Totalview debugger\n"); 2223ba16761SJacob Faibussowitsch ierr = (*PetscErrorPrintf)("On Windows use Developer Studio(MSDEV)\n"); 22341e02c4dSJunchao Zhang PETSCABORT(PETSC_COMM_WORLD, PETSC_ERR_SUP_SYS); 224e5c89e4eSSatish Balay #else 22563a3b9bcSJacob Faibussowitsch if (PetscUnlikely(PetscGetDisplay(display, sizeof(display)))) { 226cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine display\n"); 22711cc89d2SBarry Smith return PETSC_ERR_SYS; 2285f80ce2aSJacob Faibussowitsch } 22963a3b9bcSJacob Faibussowitsch if (PetscUnlikely(PetscGetProgramName(program, sizeof(program)))) { 230cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 23111cc89d2SBarry Smith return PETSC_ERR_SYS; 232e5c89e4eSSatish Balay } 2335f80ce2aSJacob Faibussowitsch if (PetscUnlikely(!program[0])) { 234cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Cannot determine program name needed to attach debugger\n"); 235cfbfffeaSBarry Smith return PETSC_ERR_SYS; 236cfbfffeaSBarry Smith } 237ca85ed89SBarry Smith 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"); } 238e5c89e4eSSatish Balay child = (int)fork(); 2395f80ce2aSJacob Faibussowitsch if (PetscUnlikely(child < 0)) { 240cfbfffeaSBarry Smith ierr = (*PetscErrorPrintf)("PetscAttachDebugger: Error in fork() prior to attaching debugger\n"); 24111cc89d2SBarry Smith return PETSC_ERR_SYS; 242e5c89e4eSSatish Balay } 243bf4d2887SBarry Smith petscindebugger = PETSC_TRUE; 244e5c89e4eSSatish Balay 245e5c89e4eSSatish Balay /* 246e5c89e4eSSatish Balay Swap role the parent and child. This is (I think) so that control c typed 247e5c89e4eSSatish Balay in the debugger goes to the correct process. 248e5c89e4eSSatish Balay */ 249234acd79SBarry Smith #if !defined(PETSC_DO_NOT_SWAP_CHILD_FOR_DEBUGGER) 25063a3b9bcSJacob Faibussowitsch child = child ? 0 : (int)getppid(); 251234acd79SBarry Smith #endif 252e5c89e4eSSatish Balay 253e5c89e4eSSatish Balay if (child) { /* I am the parent, will run the debugger */ 254e5c89e4eSSatish Balay const char *args[10]; 255e5c89e4eSSatish Balay char pid[10]; 2565e96ac45SJed Brown PetscInt j, jj; 2570e9bae81SBarry Smith PetscBool isdbx, isidb, isxldb, isxxgdb, isups, isxdb, isworkshop, isddd, iskdbg, islldb; 258e5c89e4eSSatish Balay 2599566063dSJacob Faibussowitsch PetscCall(PetscGetHostName(hostname, sizeof(hostname))); 260e5c89e4eSSatish Balay /* 261e5c89e4eSSatish Balay We need to send a continue signal to the "child" process on the 262e5c89e4eSSatish Balay alpha, otherwise it just stays off forever 263e5c89e4eSSatish Balay */ 264e5c89e4eSSatish Balay #if defined(PETSC_NEED_KILL_FOR_DEBUGGER) 265e5c89e4eSSatish Balay kill(child, SIGCONT); 266e5c89e4eSSatish Balay #endif 267a364092eSJacob Faibussowitsch PetscCall(PetscSNPrintf(pid, PETSC_STATIC_ARRAY_LENGTH(pid), "%d", child)); 268e5c89e4eSSatish Balay 2699566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xxgdb", &isxxgdb)); 2709566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ddd", &isddd)); 2719566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "kdbg", &iskdbg)); 2729566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "ups", &isups)); 2739566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xldb", &isxldb)); 2749566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "xdb", &isxdb)); 2759566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "dbx", &isdbx)); 2769566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "idb", &isidb)); 2779566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "workshop", &isworkshop)); 2789566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(PetscDebugger, "lldb", &islldb)); 279e5c89e4eSSatish Balay 280e5c89e4eSSatish Balay if (isxxgdb || isups || isddd) { 2819371c9d4SSatish Balay args[1] = program; 2829371c9d4SSatish Balay args[2] = pid; 2839371c9d4SSatish Balay args[3] = "-display"; 2849371c9d4SSatish Balay args[0] = PetscDebugger; 2859371c9d4SSatish Balay args[4] = display; 2869371c9d4SSatish Balay args[5] = NULL; 287c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 288e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) { 289e5c89e4eSSatish Balay perror("Unable to start debugger"); 290e5c89e4eSSatish Balay exit(0); 291e5c89e4eSSatish Balay } 292bf902449SSatish Balay } else if (iskdbg) { 2939371c9d4SSatish Balay args[1] = "-p"; 2949371c9d4SSatish Balay args[2] = pid; 2959371c9d4SSatish Balay args[3] = program; 2969371c9d4SSatish Balay args[4] = "-display"; 2979371c9d4SSatish Balay args[0] = PetscDebugger; 2989371c9d4SSatish Balay args[5] = display; 2999371c9d4SSatish Balay args[6] = NULL; 300c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[3], pid, hostname); 301bf902449SSatish Balay if (execvp(args[0], (char **)args) < 0) { 302bf902449SSatish Balay perror("Unable to start debugger"); 303bf902449SSatish Balay exit(0); 304bf902449SSatish Balay } 305e5c89e4eSSatish Balay } else if (isxldb) { 3069371c9d4SSatish Balay args[1] = "-a"; 3079371c9d4SSatish Balay args[2] = pid; 3089371c9d4SSatish Balay args[3] = program; 3099371c9d4SSatish Balay args[4] = "-display"; 3109371c9d4SSatish Balay args[0] = PetscDebugger; 3119371c9d4SSatish Balay args[5] = display; 3129371c9d4SSatish Balay args[6] = NULL; 313c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s %s on %s\n", args[0], args[1], pid, hostname); 314e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) { 315e5c89e4eSSatish Balay perror("Unable to start debugger"); 316e5c89e4eSSatish Balay exit(0); 317e5c89e4eSSatish Balay } 318e5c89e4eSSatish Balay } else if (isworkshop) { 3199371c9d4SSatish Balay args[1] = "-s"; 3209371c9d4SSatish Balay args[2] = pid; 3219371c9d4SSatish Balay args[3] = "-D"; 3229371c9d4SSatish Balay args[4] = "-"; 3239371c9d4SSatish Balay args[0] = PetscDebugger; 3249371c9d4SSatish Balay args[5] = pid; 3259371c9d4SSatish Balay args[6] = "-display"; 3269371c9d4SSatish Balay args[7] = display; 3279371c9d4SSatish Balay args[8] = NULL; 328c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s on %s\n", args[0], pid, hostname); 329e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) { 330e5c89e4eSSatish Balay perror("Unable to start debugger"); 331e5c89e4eSSatish Balay exit(0); 332e5c89e4eSSatish Balay } 3335e96ac45SJed Brown } else { 3345e96ac45SJed Brown j = 0; 335c823fc1fSBarry Smith if (UseDebugTerminal) { 336ace3abfcSBarry Smith PetscBool cmp; 337bbcf679cSJacob Faibussowitsch char *tmp, *tmp1 = NULL; 3389566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(DebugTerminal, "Terminal", 8, &cmp)); 339c823fc1fSBarry Smith if (cmp) { 340c823fc1fSBarry Smith char command[1024]; 3419483a8a2SBarry Smith if (islldb) PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"lldb -p %s \"'\n", pid)); 3429483a8a2SBarry Smith else { 3439483a8a2SBarry Smith char fullprogram[PETSC_MAX_PATH_LEN]; 3449483a8a2SBarry Smith PetscCall(PetscGetFullPath(program, fullprogram, sizeof(fullprogram))); 3459483a8a2SBarry Smith PetscCall(PetscSNPrintf(command, sizeof(command), "osascript -e 'tell app \"Terminal\" to do script \"%s %s %s \"'\n", PetscDebugger, fullprogram, pid)); 3469483a8a2SBarry Smith } 347accbd18bSBarry Smith #if defined(PETSC_HAVE_POPEN) 3489566063dSJacob Faibussowitsch PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, command, "r", NULL)); 349accbd18bSBarry Smith #else 350accbd18bSBarry Smith printf("-debug_terminal Terminal is not available on this system since PETSC_HAVE_POPEN is not defined in this configuration\n"); 351accbd18bSBarry Smith #endif 352c823fc1fSBarry Smith exit(0); 353c823fc1fSBarry Smith } 354c823fc1fSBarry Smith 3559566063dSJacob Faibussowitsch PetscCall(PetscStrncmp(DebugTerminal, "screen", 6, &cmp)); 3569566063dSJacob Faibussowitsch if (!cmp) PetscCall(PetscStrncmp(DebugTerminal, "gnome-terminal", 6, &cmp)); 3575e96ac45SJed Brown if (cmp) display[0] = 0; /* when using screen, we never pass -display */ 3585e96ac45SJed Brown args[j++] = tmp = DebugTerminal; 3595e96ac45SJed Brown if (display[0]) { 3609371c9d4SSatish Balay args[j++] = "-display"; 3619371c9d4SSatish Balay args[j++] = display; 3625e96ac45SJed Brown } 3635e96ac45SJed Brown while (*tmp) { 3649566063dSJacob Faibussowitsch PetscCall(PetscStrchr(tmp, ' ', &tmp1)); 3655e96ac45SJed Brown if (!tmp1) break; 3665e96ac45SJed Brown *tmp1 = 0; 3675e96ac45SJed Brown tmp = tmp1 + 1; 3685e96ac45SJed Brown args[j++] = tmp; 3695e96ac45SJed Brown } 3705e96ac45SJed Brown } 371b59f628eSBarry Smith args[j++] = PetscDebugger; 3725e96ac45SJed Brown jj = j; 373bf4d2887SBarry Smith /* this is for default gdb */ 374bf4d2887SBarry Smith args[j++] = program; 375bf4d2887SBarry Smith args[j++] = pid; 376bf4d2887SBarry Smith args[j++] = NULL; 3775e96ac45SJed Brown 378e5c89e4eSSatish Balay if (isidb) { 3795e96ac45SJed Brown j = jj; 3805e96ac45SJed Brown args[j++] = "-pid"; 3815e96ac45SJed Brown args[j++] = pid; 3825e96ac45SJed Brown args[j++] = "-gdb"; 3835e96ac45SJed Brown args[j++] = program; 38402c9f0b5SLisandro Dalcin args[j++] = NULL; 385e5c89e4eSSatish Balay } 3860e9bae81SBarry Smith if (islldb) { 3870e9bae81SBarry Smith j = jj; 3880e9bae81SBarry Smith args[j++] = "-p"; 3890e9bae81SBarry Smith args[j++] = pid; 39002c9f0b5SLisandro Dalcin args[j++] = NULL; 3910e9bae81SBarry Smith } 392e5c89e4eSSatish Balay if (isdbx) { 3935e96ac45SJed Brown j = jj; 3948d359177SBarry Smith #if defined(PETSC_USE_P_FOR_DEBUGGER) 3955e96ac45SJed Brown args[j++] = "-p"; 3965e96ac45SJed Brown args[j++] = pid; 3975e96ac45SJed Brown args[j++] = program; 398e5c89e4eSSatish Balay #elif defined(PETSC_USE_LARGEP_FOR_DEBUGGER) 3995e96ac45SJed Brown args[j++] = "-l"; 4005e96ac45SJed Brown args[j++] = "ALL"; 4015e96ac45SJed Brown args[j++] = "-P"; 4025e96ac45SJed Brown args[j++] = pid; 4035e96ac45SJed Brown args[j++] = program; 404e5c89e4eSSatish Balay #elif defined(PETSC_USE_A_FOR_DEBUGGER) 4055e96ac45SJed Brown args[j++] = "-a"; 4065e96ac45SJed Brown args[j++] = pid; 407e5c89e4eSSatish Balay #elif defined(PETSC_USE_PID_FOR_DEBUGGER) 4085e96ac45SJed Brown args[j++] = "-pid"; 4095e96ac45SJed Brown args[j++] = pid; 4105e96ac45SJed Brown args[j++] = program; 411493de400SSatish Balay #else 412493de400SSatish Balay args[j++] = program; 413493de400SSatish Balay args[j++] = pid; 4148d359177SBarry Smith #endif 41502c9f0b5SLisandro Dalcin args[j++] = NULL; 416e5c89e4eSSatish Balay } 417c823fc1fSBarry Smith if (UseDebugTerminal) { 418c5888dd7SBarry 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); 419c5888dd7SBarry Smith else printf("PETSC: Attaching %s to %s on pid %s on %s\n", PetscDebugger, program, pid, hostname); 420a297a907SKarl Rupp 4215e96ac45SJed Brown if (execvp(args[0], (char **)args) < 0) { 4225e96ac45SJed Brown perror("Unable to start debugger in xterm"); 4235e96ac45SJed Brown exit(0); 4245e96ac45SJed Brown } 4255e96ac45SJed Brown } else { 426c5888dd7SBarry Smith printf("PETSC: Attaching %s to %s of pid %s on %s\n", PetscDebugger, program, pid, hostname); 427e5c89e4eSSatish Balay if (execvp(args[0], (char **)args) < 0) { 428e5c89e4eSSatish Balay perror("Unable to start debugger"); 429e5c89e4eSSatish Balay exit(0); 430e5c89e4eSSatish Balay } 431e5c89e4eSSatish Balay } 432e5c89e4eSSatish Balay } 433e5c89e4eSSatish Balay } else { /* I am the child, continue with user code */ 434e5c89e4eSSatish Balay sleeptime = 10; /* default to sleep waiting for debugger */ 4359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-debugger_pause", &sleeptime, NULL)); 436e5c89e4eSSatish Balay if (sleeptime < 0) sleeptime = -sleeptime; 437e5c89e4eSSatish Balay #if defined(PETSC_NEED_DEBUGGER_NO_SLEEP) 438e5c89e4eSSatish Balay /* 439e5c89e4eSSatish Balay HP cannot attach process to sleeping debugger, hence count instead 440e5c89e4eSSatish Balay */ 441e5c89e4eSSatish Balay { 442e5c89e4eSSatish Balay PetscReal x = 1.0; 443e5c89e4eSSatish Balay int i = 10000000; 444e5c89e4eSSatish Balay while (i--) x++; /* cannot attach to sleeper */ 445e5c89e4eSSatish Balay } 446e5c89e4eSSatish Balay #elif defined(PETSC_HAVE_SLEEP_RETURNS_EARLY) 447e5c89e4eSSatish Balay /* 448e5c89e4eSSatish Balay IBM sleep may return at anytime, hence must see if there is more time to sleep 449e5c89e4eSSatish Balay */ 450e5c89e4eSSatish Balay { 451e5c89e4eSSatish Balay int left = sleeptime; 452a297a907SKarl Rupp while (left > 0) left = PetscSleep(left) - 1; 453e5c89e4eSSatish Balay } 454e5c89e4eSSatish Balay #else 4553ba16761SJacob Faibussowitsch PetscCall(PetscSleep(sleeptime)); 456e5c89e4eSSatish Balay #endif 457e5c89e4eSSatish Balay } 458e5c89e4eSSatish Balay #endif 4593ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 460e5c89e4eSSatish Balay } 461e5c89e4eSSatish Balay 462e5c89e4eSSatish Balay /*@C 463e5c89e4eSSatish Balay PetscAttachDebuggerErrorHandler - Error handler that attaches 464e5c89e4eSSatish Balay a debugger to a running process when an error is detected. 465e5c89e4eSSatish Balay This routine is useful for examining variables, etc. 466e5c89e4eSSatish Balay 467*cc4c1da9SBarry Smith Not Collective, No Fortran Support 468e5c89e4eSSatish Balay 469e5c89e4eSSatish Balay Input Parameters: 470e32f2f54SBarry Smith + comm - communicator over which error occurred 4716e25c4a1SBarry Smith . line - the line number of the error (usually indicated by `__LINE__` in the calling routine) 4726e25c4a1SBarry Smith . fun - the function name of the calling routine 4736e25c4a1SBarry Smith . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine) 47410450e9eSJacob Faibussowitsch . mess - an error text string, usually just printed to the screen 47510450e9eSJacob Faibussowitsch . num - the generic error number 476811af0c4SBarry Smith . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT` 477e5c89e4eSSatish Balay - ctx - error handler context 478e5c89e4eSSatish Balay 479e5c89e4eSSatish Balay Level: developer 480e5c89e4eSSatish Balay 481e5c89e4eSSatish Balay Notes: 4826e25c4a1SBarry Smith By default the GNU debugger, gdb, is used except on macOS where lldb is used. Alternatives are cuda-gdb, lldb, dbx and 483e5c89e4eSSatish Balay xxgdb,xldb (on IBM rs6000), xdb (on HP-UX). 484e5c89e4eSSatish Balay 485e5c89e4eSSatish Balay Most users need not directly employ this routine and the other error 486e5c89e4eSSatish Balay handlers, but can instead use the simplified interface SETERR, which has 487e5c89e4eSSatish Balay the calling sequence 4886e25c4a1SBarry Smith .vb 4896e25c4a1SBarry Smith SETERRQ(PETSC_COMM_SELF, number, p, message) 4906e25c4a1SBarry Smith .ve 491e5c89e4eSSatish Balay 492811af0c4SBarry Smith Use `PetscPushErrorHandler()` to set the desired error handler. The 493e5c89e4eSSatish Balay currently available PETSc error handlers are 49420f4b53cSBarry Smith .vb 49520f4b53cSBarry Smith PetscTraceBackErrorHandler() 49620f4b53cSBarry Smith PetscAttachDebuggerErrorHandler() 49720f4b53cSBarry Smith PetscAbortErrorHandler() 49820f4b53cSBarry Smith .ve 499e5c89e4eSSatish Balay or you may write your own. 500e5c89e4eSSatish Balay 5016e25c4a1SBarry Smith Developer Note: 502811af0c4SBarry Smith This routine calls abort instead of returning because if it returned then `MPI_Abort()` would get called which can generate an exception 50369412655SBarry Smith causing the debugger to be attached again in a cycle. 50469412655SBarry Smith 505db781477SPatrick Sanan .seealso: `PetscSetDebuggerFromString()`, `PetscSetDebugger()`, `PetscSetDefaultDebugger()`, `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, 506db781477SPatrick Sanan `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscEmacsClientErrorHandler()`, `PetscReturnErrorHandler()`, `PetscSetDebugTermainal()` 507e5c89e4eSSatish Balay @*/ 508d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode num, PetscErrorType p, const char *mess, void *ctx) 509d71ae5a4SJacob Faibussowitsch { 5103ba16761SJacob Faibussowitsch PetscErrorCode ierr; 51110450e9eSJacob Faibussowitsch 51210450e9eSJacob Faibussowitsch (void)comm; 51310450e9eSJacob Faibussowitsch (void)num; 51410450e9eSJacob Faibussowitsch (void)p; 51510450e9eSJacob Faibussowitsch (void)ctx; 516e5c89e4eSSatish Balay if (!mess) mess = " "; 517e5c89e4eSSatish Balay 5183ba16761SJacob Faibussowitsch if (fun) ierr = (*PetscErrorPrintf)("%s() at %s:%d %s\n", fun, file, line, mess); 5193ba16761SJacob Faibussowitsch else ierr = (*PetscErrorPrintf)("%s:%d %s\n", file, line, mess); 520e5c89e4eSSatish Balay 5213ba16761SJacob Faibussowitsch ierr = PetscAttachDebugger(); 5223ba16761SJacob Faibussowitsch (void)ierr; 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 527e5c89e4eSSatish Balay /*@C 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 532*cc4c1da9SBarry 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 @*/ 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