Changeset 32422 in vbox
- Timestamp:
- Sep 10, 2010 4:48:22 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
r32413 r32422 53 53 # include <sys/systeminfo.h> 54 54 # include <sys/mman.h> 55 # include <ucontext.h> 55 56 #endif /* RT_OS_SOLARIS */ 56 57 … … 63 64 static RTNATIVETHREAD volatile g_CoreDumpThread = NIL_RTNATIVETHREAD; 64 65 static bool volatile g_fCoreDumpSignalSetup = false; 65 static bool volatile g_fCoreDumpDeliberate = false;66 66 static uint32_t volatile g_fCoreDumpFlags = 0; 67 67 static char g_szCoreDumpDir[PATH_MAX] = { 0 }; … … 1275 1275 { 1276 1276 CORELOGRELSYS((CORELOG_NAME "rtCoreDumperSuspendThreads: possible thread bomb!?\n")); 1277 rc = VERR_ GENERAL_FAILURE; /* @todo better error code */1277 rc = VERR_TIMEOUT; 1278 1278 } 1279 1279 return rc; … … 1929 1929 * @param pVBoxCore Pointer to a core object. 1930 1930 * @param pContext Pointer to the caller context thread. 1931 * @param pszCoreFilePath Path to the core file (Optional, can be NULL). 1931 1932 * 1932 1933 * @remarks Halts all threads. 1933 1934 * @return IPRT status code. 1934 1935 */ 1935 static int rtCoreDumperCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext )1936 static int rtCoreDumperCreateCore(PVBOXCORE pVBoxCore, ucontext_t *pContext, const char *pszCoreFilePath) 1936 1937 { 1937 1938 AssertReturn(pVBoxCore, VERR_INVALID_POINTER); … … 1958 1959 1959 1960 /* 1960 * If no output directory is specified, use current directory. 1961 */ 1962 if (g_szCoreDumpDir[0] == '\0') 1963 g_szCoreDumpDir[0] = '.'; 1964 1965 if (g_szCoreDumpFile[0] == '\0') 1966 { 1967 /* We cannot call RTPathAbs*() as they call getcwd() which calls malloc. */ 1968 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s.%d", 1969 g_szCoreDumpDir, pVBoxProc->pszExecName, (int)pVBoxProc->Process); 1961 * If a path has been specified, use it. Otherwise use the global path. 1962 */ 1963 if (!pszCoreFilePath) 1964 { 1965 /* 1966 * If no output directory is specified, use current directory. 1967 */ 1968 if (g_szCoreDumpDir[0] == '\0') 1969 g_szCoreDumpDir[0] = '.'; 1970 1971 if (g_szCoreDumpFile[0] == '\0') 1972 { 1973 /* We cannot call RTPathAbs*() as they call getcwd() which calls malloc. */ 1974 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s.%d", 1975 g_szCoreDumpDir, pVBoxProc->pszExecName, (int)pVBoxProc->Process); 1976 } 1977 else 1978 RTStrPrintf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s", g_szCoreDumpDir, g_szCoreDumpFile); 1970 1979 } 1971 1980 else 1972 RTStr Printf(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), "%s/core.vb.%s", g_szCoreDumpDir, g_szCoreDumpFile);1981 RTStrCopy(pVBoxCore->szCorePath, sizeof(pVBoxCore->szCorePath), pszCoreFilePath); 1973 1982 1974 1983 CORELOG((CORELOG_NAME "CreateCore: Taking Core %s from Thread %d\n", pVBoxCore->szCorePath, (int)pVBoxProc->hCurThread)); … … 2081 2090 * 2082 2091 * @param pContext The context of the caller. 2092 * @param pszOutputFile Path of the core file. If NULL is passed, the 2093 * global path passed in RTCoreDumperSetup will 2094 * be used. 2083 2095 * @returns IPRT status code. 2084 2096 */ 2085 static int rtCoreDumperTakeDump(ucontext_t *pContext )2097 static int rtCoreDumperTakeDump(ucontext_t *pContext, const char *pszOutputFile) 2086 2098 { 2087 2099 if (!pContext) … … 2098 2110 VBOXCORE VBoxCore; 2099 2111 RT_ZERO(VBoxCore); 2100 int rc = rtCoreDumperCreateCore(&VBoxCore, pContext );2112 int rc = rtCoreDumperCreateCore(&VBoxCore, pContext, pszOutputFile); 2101 2113 if (RT_SUCCESS(rc)) 2102 2114 { … … 2135 2147 if (fRc) 2136 2148 { 2137 rc = rtCoreDumperTakeDump((ucontext_t *)pvArg );2149 rc = rtCoreDumperTakeDump((ucontext_t *)pvArg, NULL /* Use Global Core filepath */); 2138 2150 ASMAtomicWriteHandle(&g_CoreDumpThread, NIL_RTNATIVETHREAD); 2139 2151 … … 2215 2227 RTDECL(int) RTCoreDumperTakeDump(const char *pszOutputFile, bool fLiveCore) 2216 2228 { 2217 /** @todo r=bird: No setup should be required for this call and it 2218 * shouldn't change the globals. 2219 * 2220 * Would probably be best to serialize RTCoreDumperTakeDump callers using a 2221 * lazily initialized critsect (see RTOnce) and use different globals to 2222 * communicate with the signal handlers. 2223 * 2224 * Another improvement is to use getcontext() to get the thread context and 2225 * call rtCoreDumperTakeDump directly. Extend rtCoreDumperTakeDump so that 2226 * it takes pszOutputFile as an optional argument. Mask the other fatal + 2227 * SIGUSR2 while doing this. 2228 */ 2229 2230 /* 2231 * Validate input. 2232 */ 2233 if (ASMAtomicReadBool(&g_fCoreDumpSignalSetup) == false) 2234 return VERR_WRONG_ORDER; 2235 2236 uint32_t fFlags = ASMAtomicReadU32(&g_fCoreDumpFlags); 2237 if (fLiveCore && !(fFlags & RTCOREDUMPER_FLAGS_LIVE_CORE)) 2238 return VERR_INVALID_PARAMETER; 2239 2240 if (!fLiveCore && !(fFlags & RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP)) 2241 return VERR_INVALID_PARAMETER; 2242 2243 RT_ZERO(g_szCoreDumpFile); 2244 if (pszOutputFile) 2245 RTStrCopy(g_szCoreDumpFile, sizeof(g_szCoreDumpFile), pszOutputFile); 2246 2247 ASMAtomicWriteBool(&g_fCoreDumpDeliberate, true); 2248 2249 if (fLiveCore == false) 2250 raise(SIGSEGV); 2229 ucontext_t Context; 2230 int rc = getcontext(&Context); 2231 if (!rc) 2232 { 2233 /* 2234 * Block SIGSEGV and co. while we write the core. 2235 */ 2236 sigset_t SigSet, OldSigSet; 2237 sigemptyset(&SigSet); 2238 sigaddset(&SigSet, SIGSEGV); 2239 sigaddset(&SigSet, SIGBUS); 2240 sigaddset(&SigSet, SIGTRAP); 2241 sigaddset(&SigSet, SIGUSR2); 2242 pthread_sigmask(SIG_BLOCK, &SigSet, &OldSigSet); 2243 rc = rtCoreDumperTakeDump(&Context, pszOutputFile); 2244 if (!fLiveCore) 2245 { 2246 signal(SIGSEGV, SIG_DFL); 2247 signal(SIGBUS, SIG_DFL); 2248 signal(SIGTRAP, SIG_DFL); 2249 if (RT_SUCCESS(rc)) 2250 raise(SIGKILL); 2251 else 2252 abort(); 2253 } 2254 pthread_sigmask(SIG_SETMASK, &OldSigSet, NULL); 2255 } 2251 2256 else 2252 raise(SIGUSR2); 2253 2254 ASMAtomicWriteBool(&g_fCoreDumpDeliberate, false); 2255 return VINF_SUCCESS; 2257 { 2258 CORELOGRELSYS(("RTCoreDumperTakeDump: getcontext failed rc=%d.\n")); 2259 rc = VERR_INVALID_CONTEXT; 2260 } 2261 2262 return rc; 2256 2263 } 2257 2264 … … 2267 2274 VERR_INVALID_PARAMETER); 2268 2275 2269 /** @todo r=bird: The idea here was that we shouldn't register the handler 2270 * more than once. I.e. skip it if g_fCoreDumpSignalSetup and the 2271 * flags didn't change in any way. The rational/usecase is that that 2272 * allows the user to chain handlers before our SIGSEGV/SIGBUS/SIGTRAP 2273 * core dumping + crashing handler. Since we're registering our stuff 2274 * in Main somewhere it's important that only the first call messes with 2275 * the signal handlers. The front end could for instance do a 2276 * RTCoreDumperSetup(NULL, RTCOREDUMPER_FLAGS_REPLACE_SYSTEM_DUMP | 2277 * RTCOREDUMPER_FLAGS_LIVE_CORE) call in it's main() before setting up 2278 * it's own SIGBUS/SIGSEGV/SIGTRAP handlers. 2279 * 2280 * Adding the conditional registration via the two flags complicates 2281 * the implementation of this use case. */ 2282 2283 /* 2284 * Install core dump signal handler. 2276 /* 2277 * Install core dump signal handler only if the flags changed or if it's the first time. 2285 2278 */ 2286 2279 if ( ASMAtomicReadBool(&g_fCoreDumpSignalSetup) == false
Note:
See TracChangeset
for help on using the changeset viewer.