void CrashHandlerWindows::handleCrash(int crashType, void * crashExtraInfo, int fpeCode) { Autolock autoLock(&m_Lock); // Run the callbacks for(std::vector<CrashHandler::CrashCallback>::iterator it = m_crashCallbacks.begin(); it != m_crashCallbacks.end(); ++it) { (*it)(); } m_pCrashInfo->signal = crashType; m_pCrashInfo->code = fpeCode; PEXCEPTION_POINTERS pointers = reinterpret_cast<PEXCEPTION_POINTERS>(crashExtraInfo); // Copy CONTEXT to crash info structure PCONTEXT context = reinterpret_cast<PCONTEXT>(m_pCrashInfo->contextRecord); ARX_STATIC_ASSERT(sizeof(m_pCrashInfo->contextRecord) >= sizeof(*context), "buffer too small"); memset(context, 0, sizeof(*context)); EXCEPTION_POINTERS fakePointers; EXCEPTION_RECORD exception; if(pointers) { u32 code = m_pCrashInfo->exceptionCode = pointers->ExceptionRecord->ExceptionCode; m_pCrashInfo->address = u64(pointers->ExceptionRecord->ExceptionAddress); m_pCrashInfo->hasAddress = true; if(code == EXCEPTION_ACCESS_VIOLATION || code == EXCEPTION_IN_PAGE_ERROR) { m_pCrashInfo->memory = pointers->ExceptionRecord->ExceptionInformation[1]; m_pCrashInfo->hasMemory = true; } #if ARX_ARCH == ARX_ARCH_X86 m_pCrashInfo->stack = pointers->ContextRecord->Esp; m_pCrashInfo->hasStack = true; m_pCrashInfo->frame = pointers->ContextRecord->Ebp; m_pCrashInfo->hasFrame = true; #elif ARX_ARCH == ARX_ARCH_X86_64 m_pCrashInfo->stack = pointers->ContextRecord->Rsp; m_pCrashInfo->hasStack = true; #endif std::memcpy(context, pointers->ContextRecord, sizeof(*context)); } else { RtlCaptureContext(context); std::memset(&exception, 0, sizeof(exception)); fakePointers.ContextRecord = context; fakePointers.ExceptionRecord = &exception; pointers = &fakePointers; } // Get current thread id m_pCrashInfo->threadId = u32(GetCurrentThreadId()); writeCrashDump(pointers); // Try to spawn a sub-process to process the crash info STARTUPINFO si; memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); PROCESS_INFORMATION pi; memset(&pi, 0, sizeof(PROCESS_INFORMATION)); BOOL created = CreateProcessW(m_exe, m_args.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if(created) { while(true) { if(m_pCrashInfo->exitLock.try_wait()) { break; } if(WaitForSingleObject(pi.hProcess, 100) != WAIT_TIMEOUT) { break; } } TerminateProcess(GetCurrentProcess(), 1); unregisterCrashHandlers(); std::abort(); } // Fallback: process the crash info in-process unregisterCrashHandlers(); processCrash(); std::abort(); }
void CrashHandlerImpl::shutdown() { Autolock autoLock(&m_Lock); unregisterCrashHandlers(); destroySharedMemory(); }