mirror of
https://github.com/beefytech/Beef.git
synced 2025-07-12 19:26:00 +02:00
Added ability to catch llvm errs(), shared crashcatcher object
This commit is contained in:
parent
76e29d385b
commit
f1eafa8d81
4 changed files with 274 additions and 113 deletions
|
@ -1,5 +1,4 @@
|
|||
#include "CrashCatcher.h"
|
||||
#include "../util/CritSect.h"
|
||||
#include "../util/Dictionary.h"
|
||||
#include <commdlg.h>
|
||||
#include <time.h>
|
||||
|
@ -51,15 +50,7 @@ static SYMFUNCTIONTABLEACCESSPROC gSymFunctionTableAccess = NULL;
|
|||
static SYMGETMODULEBASEPROC gSymGetModuleBase = NULL;
|
||||
static SYMGETSYMFROMADDRPROC gSymGetSymFromAddr = NULL;
|
||||
static SYMGETLINEFROMADDR gSymGetLineFromAddr = NULL;
|
||||
static Array<CrashInfoFunc> gCrashInfoFuncs;
|
||||
static StringT<0> gCrashInfo;
|
||||
static bool gCrashed = false;
|
||||
extern CritSect gBfpCritSect;
|
||||
|
||||
static EXCEPTION_POINTERS* gExceptionPointers = NULL;
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER gPreviousFilter = NULL;
|
||||
|
||||
static bool gDebugError = false;
|
||||
|
||||
static bool CreateMiniDump(EXCEPTION_POINTERS* pep, const StringImpl& filePath);
|
||||
|
||||
|
@ -162,7 +153,6 @@ struct
|
|||
{ 0xFFFFFFFF, "" }
|
||||
};
|
||||
|
||||
static bool gUseDefaultFonts;
|
||||
static HFONT gDialogFont;
|
||||
static HFONT gBoldFont;
|
||||
static String gErrorTitle;
|
||||
|
@ -171,10 +161,9 @@ static HWND gDebugButtonWindow = NULL;
|
|||
static HWND gYesButtonWindow = NULL;
|
||||
static HWND gNoButtonWindow = NULL;
|
||||
static bool gExiting = false;
|
||||
static BfpCrashReportKind gCrashReportKind = BfpCrashReportKind_Default;
|
||||
|
||||
static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_COMMAND:
|
||||
|
@ -198,7 +187,7 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
|
||||
if (::GetSaveFileNameW(&openFileName))
|
||||
{
|
||||
CreateMiniDump(gExceptionPointers, UTF8Encode(fileName));
|
||||
CreateMiniDump(CrashCatcher::Get()->mExceptionPointers, UTF8Encode(fileName));
|
||||
}
|
||||
}
|
||||
else if (hwndCtl == gNoButtonWindow)
|
||||
|
@ -207,7 +196,7 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
}
|
||||
else if (hwndCtl == gDebugButtonWindow)
|
||||
{
|
||||
gDebugError = true;
|
||||
CrashCatcher::Get()->mDebugError = true;
|
||||
gExiting = true;
|
||||
}
|
||||
}
|
||||
|
@ -222,6 +211,8 @@ static LRESULT CALLBACK SEHWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
|
||||
static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& errorText)
|
||||
{
|
||||
bool gUseDefaultFonts;
|
||||
|
||||
HINSTANCE gHInstance = ::GetModuleHandle(NULL);
|
||||
|
||||
OSVERSIONINFO aVersionInfo;
|
||||
|
@ -247,7 +238,6 @@ static void ShowErrorDialog(const StringImpl& errorTitle, const StringImpl& erro
|
|||
gErrorTitle = errorTitle;
|
||||
gErrorText = errorText;
|
||||
|
||||
|
||||
WNDCLASSW wc;
|
||||
wc.style = 0;
|
||||
wc.cbClsExtra = 0;
|
||||
|
@ -810,18 +800,18 @@ static String GetVersion(const StringImpl& fileName)
|
|||
|
||||
static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
||||
{
|
||||
if (gCrashed)
|
||||
if (CrashCatcher::Get()->mCrashed)
|
||||
return;
|
||||
gCrashed = true;
|
||||
CrashCatcher::Get()->mCrashed = true;
|
||||
|
||||
HMODULE hMod = GetModuleHandleA(NULL);
|
||||
|
||||
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
|
||||
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((uint8*)hMod + pDosHdr->e_lfanew);
|
||||
bool isCLI = pNtHdr->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
if (gCrashReportKind == BfpCrashReportKind_GUI)
|
||||
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_GUI)
|
||||
isCLI = false;
|
||||
else if ((gCrashReportKind == BfpCrashReportKind_Console) || (gCrashReportKind == BfpCrashReportKind_PrintOnly))
|
||||
else if ((CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_Console) || (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_PrintOnly))
|
||||
isCLI = true;
|
||||
|
||||
bool hasImageHelp = LoadImageHelp();
|
||||
|
@ -858,12 +848,12 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
|||
aDebugDump += StrFormat("Crash minidump saved as %s\n", crashPath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
for (auto func : gCrashInfoFuncs)
|
||||
|
||||
for (auto func : CrashCatcher::Get()->mCrashInfoFuncs)
|
||||
func();
|
||||
|
||||
aDebugDump.Append(gCrashInfo);
|
||||
|
||||
aDebugDump.Append(CrashCatcher::Get()->mCrashInfo);
|
||||
|
||||
for (int i = 0; i < (int)aDebugDump.length(); i++)
|
||||
{
|
||||
char c = aDebugDump[i];
|
||||
|
@ -994,26 +984,31 @@ static void DoHandleDebugEvent(LPEXCEPTION_POINTERS lpEP)
|
|||
|
||||
CrashCatcher::CrashCatcher()
|
||||
{
|
||||
|
||||
mCrashed = false;
|
||||
mInitialized = false;
|
||||
mExceptionPointers = NULL;
|
||||
mPreviousFilter = NULL;
|
||||
mDebugError = false;
|
||||
mCrashReportKind = BfpCrashReportKind_Default;
|
||||
}
|
||||
|
||||
static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
||||
{
|
||||
OutputDebugStrF("SEH Filter! CraskReportKind:%d\n", gCrashReportKind);
|
||||
OutputDebugStrF("SEH Filter! CraskReportKind:%d\n", CrashCatcher::Get()->mCrashReportKind);
|
||||
|
||||
if (gCrashReportKind == BfpCrashReportKind_None)
|
||||
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_None)
|
||||
{
|
||||
OutputDebugStrF("Silent Exiting\n");
|
||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
AutoCrit autoCrit(CrashCatcher::Get()->mBfpCritSect);
|
||||
//::ExitProcess();
|
||||
//quick_exit(1);
|
||||
|
||||
if (!gCrashed)
|
||||
if (!CrashCatcher::Get()->mCrashed)
|
||||
{
|
||||
gExceptionPointers = lpExceptPtr;
|
||||
CrashCatcher::Get()->mExceptionPointers = lpExceptPtr;
|
||||
//CreateMiniDump(lpExceptPtr);
|
||||
DoHandleDebugEvent(lpExceptPtr);
|
||||
}
|
||||
|
@ -1021,7 +1016,7 @@ static long __stdcall SEHFilter(LPEXCEPTION_POINTERS lpExceptPtr)
|
|||
//if (!gDebugError)
|
||||
//SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||
|
||||
if (gCrashReportKind == BfpCrashReportKind_PrintOnly)
|
||||
if (CrashCatcher::Get()->mCrashReportKind == BfpCrashReportKind_PrintOnly)
|
||||
{
|
||||
::TerminateProcess(GetCurrentProcess(), lpExceptPtr->ExceptionRecord->ExceptionCode);
|
||||
}
|
||||
|
@ -1039,9 +1034,13 @@ static long __stdcall VectorExceptionHandler(LPEXCEPTION_POINTERS lpExceptPtr)
|
|||
|
||||
|
||||
void CrashCatcher::Init()
|
||||
{
|
||||
gPreviousFilter = SetUnhandledExceptionFilter(SEHFilter);
|
||||
OutputDebugStrF("Setting SEH filter %p\n", gPreviousFilter);
|
||||
{
|
||||
if (mInitialized)
|
||||
return;
|
||||
|
||||
mPreviousFilter = SetUnhandledExceptionFilter(SEHFilter);
|
||||
OutputDebugStrF("Setting SEH filter %p\n", mPreviousFilter);
|
||||
mInitialized = true;
|
||||
|
||||
// OutputDebugStrF("AddVectoredExceptionHandler 2\n");
|
||||
// AddVectoredExceptionHandler(0, VectorExceptionHandler);
|
||||
|
@ -1065,30 +1064,33 @@ void CrashCatcher::Test()
|
|||
|
||||
void CrashCatcher::AddCrashInfoFunc(CrashInfoFunc crashInfoFunc)
|
||||
{
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
gCrashInfoFuncs.Add(crashInfoFunc);
|
||||
AutoCrit autoCrit(mBfpCritSect);
|
||||
mCrashInfoFuncs.Add(crashInfoFunc);
|
||||
}
|
||||
|
||||
void CrashCatcher::AddInfo(const StringImpl& str)
|
||||
{
|
||||
AutoCrit autoCrit(gBfpCritSect);
|
||||
gCrashInfo.Append(str);
|
||||
AutoCrit autoCrit(mBfpCritSect);
|
||||
mCrashInfo.Append(str);
|
||||
if (!str.EndsWith('\n'))
|
||||
mCrashInfo.Append('\n');
|
||||
}
|
||||
|
||||
void CrashCatcher::Crash(const StringImpl& str)
|
||||
{
|
||||
OutputDebugStrF("CrashCatcher::Crash\n");
|
||||
|
||||
gBfpCritSect.Lock();
|
||||
gCrashInfo.Append(str);
|
||||
mBfpCritSect.Lock();
|
||||
mCrashInfo.Append(str);
|
||||
mCrashInfo.Append("\n");
|
||||
|
||||
if (gPreviousFilter == NULL)
|
||||
if (mPreviousFilter == NULL)
|
||||
{
|
||||
// A little late, but install handler now so we can catch this crash
|
||||
Init();
|
||||
}
|
||||
|
||||
gBfpCritSect.Unlock();
|
||||
mBfpCritSect.Unlock();
|
||||
|
||||
|
||||
__debugbreak();
|
||||
|
@ -1104,11 +1106,74 @@ void CrashCatcher::Crash(const StringImpl& str)
|
|||
{
|
||||
|
||||
}*/
|
||||
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void CrashCatcher::SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
||||
{
|
||||
gCrashReportKind = crashReportKind;
|
||||
mCrashReportKind = crashReportKind;
|
||||
}
|
||||
|
||||
struct CrashCatchMemory
|
||||
{
|
||||
public:
|
||||
CrashCatcher* mBpManager;
|
||||
int mABIVersion;
|
||||
};
|
||||
|
||||
#define CRASHCATCH_ABI_VERSION 1
|
||||
|
||||
static CrashCatcher* sCrashCatcher = NULL;
|
||||
CrashCatcher* CrashCatcher::Get()
|
||||
{
|
||||
if (sCrashCatcher != NULL)
|
||||
return sCrashCatcher;
|
||||
|
||||
char mutexName[128];
|
||||
sprintf(mutexName, "BfCrashCatch_mutex_%d", GetCurrentProcessId());
|
||||
char memName[128];
|
||||
sprintf(memName, "BfCrashCatch_mem_%d", GetCurrentProcessId());
|
||||
|
||||
auto mutex = ::CreateMutexA(NULL, TRUE, mutexName);
|
||||
if (mutex != NULL)
|
||||
{
|
||||
HANDLE fileMapping = ::OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, memName);
|
||||
if (fileMapping != NULL)
|
||||
{
|
||||
CrashCatchMemory* sharedMem = (CrashCatchMemory*)MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CrashCatchMemory));
|
||||
if (sharedMem != NULL)
|
||||
{
|
||||
if (sharedMem->mABIVersion == CRASHCATCH_ABI_VERSION)
|
||||
sCrashCatcher = sharedMem->mBpManager;
|
||||
::UnmapViewOfFile(sharedMem);
|
||||
}
|
||||
::CloseHandle(fileMapping);
|
||||
}
|
||||
else
|
||||
{
|
||||
fileMapping = ::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(CrashCatchMemory), memName);
|
||||
if (fileMapping != NULL)
|
||||
{
|
||||
CrashCatchMemory* sharedMem = (CrashCatchMemory*)MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CrashCatchMemory));
|
||||
if (sharedMem != NULL)
|
||||
{
|
||||
sCrashCatcher = new CrashCatcher();
|
||||
sharedMem->mBpManager = sCrashCatcher;
|
||||
sharedMem->mABIVersion = CRASHCATCH_ABI_VERSION;
|
||||
::UnmapViewOfFile(sharedMem);
|
||||
::ReleaseMutex(mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
::CloseHandle(fileMapping);
|
||||
::CloseHandle(mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sCrashCatcher == NULL)
|
||||
sCrashCatcher = new CrashCatcher();
|
||||
return sCrashCatcher;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../BeefySysLib/Common.h"
|
||||
#include "../util/CritSect.h"
|
||||
|
||||
NS_BF_BEGIN
|
||||
|
||||
|
@ -8,6 +9,17 @@ typedef void(*CrashInfoFunc)();
|
|||
|
||||
class CrashCatcher
|
||||
{
|
||||
public:
|
||||
Array<CrashInfoFunc> mCrashInfoFuncs;
|
||||
StringT<0> mCrashInfo;
|
||||
bool mCrashed;
|
||||
bool mInitialized;
|
||||
CritSect mBfpCritSect;
|
||||
EXCEPTION_POINTERS* mExceptionPointers;
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER mPreviousFilter;
|
||||
bool mDebugError;
|
||||
BfpCrashReportKind mCrashReportKind;
|
||||
|
||||
public:
|
||||
CrashCatcher();
|
||||
|
||||
|
@ -17,7 +29,9 @@ public:
|
|||
|
||||
void Test();
|
||||
void Crash(const StringImpl& str);
|
||||
void SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
||||
void SetCrashReportKind(BfpCrashReportKind crashReportKind);
|
||||
|
||||
static CrashCatcher* Get();
|
||||
};
|
||||
|
||||
NS_BF_END
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include "util/AllocDebug.h"
|
||||
|
||||
//kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
|
||||
|
||||
#pragma comment(lib, "ole32.lib")
|
||||
#pragma comment(lib, "shell32.lib")
|
||||
#pragma comment(lib, "user32.lib")
|
||||
|
@ -47,10 +45,6 @@ struct WindowsSharedInfo
|
|||
|
||||
static WindowsSharedInfo* gGlobalPlatformInfo = NULL;
|
||||
static HANDLE gGlobalMutex = 0;
|
||||
static CrashCatcher gCrashCatcher;
|
||||
|
||||
//#define HANDLE_TO_BFPFILE(val) ((BfpFile*)(val))
|
||||
//#define BFPFILE_TO_HANDLE(val) ((HANDLE)(val))
|
||||
|
||||
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
|
||||
typedef LONG KPRIORITY;
|
||||
|
@ -950,11 +944,10 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_Init(int version, BfpSystemInitFlags flag
|
|||
// Then we install our abort handler.
|
||||
signal(SIGABRT, &AbortHandler);
|
||||
|
||||
gCrashCatcher.Init();
|
||||
|
||||
CrashCatcher::Get()->Init();
|
||||
if ((flags & BfpSystemInitFlag_SilentCrash) != 0)
|
||||
gCrashCatcher.SetCrashReportKind(BfpCrashReportKind_None);
|
||||
}
|
||||
CrashCatcher::Get()->SetCrashReportKind(BfpCrashReportKind_None);
|
||||
}
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
|
||||
|
@ -964,17 +957,17 @@ BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCommandLine(int argc, char** argv)
|
|||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_SetCrashReportKind(BfpCrashReportKind crashReportKind)
|
||||
{
|
||||
gCrashCatcher.SetCrashReportKind(crashReportKind);
|
||||
CrashCatcher::Get()->SetCrashReportKind(crashReportKind);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfoFunc(BfpCrashInfoFunc crashInfoFunc)
|
||||
{
|
||||
gCrashCatcher.AddCrashInfoFunc(crashInfoFunc);
|
||||
CrashCatcher::Get()->AddCrashInfoFunc(crashInfoFunc);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_AddCrashInfo(const char* str)
|
||||
{
|
||||
gCrashCatcher.AddInfo(str);
|
||||
CrashCatcher::Get()->AddInfo(str);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_Shutdown()
|
||||
|
@ -1077,9 +1070,9 @@ BFP_EXPORT uint64 BFP_CALLTYPE BfpSystem_InterlockedCompareExchange64(uint64* pt
|
|||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_FatalError(const char* error, const char* title)
|
||||
{
|
||||
if (title != NULL)
|
||||
gCrashCatcher.Crash(String(title) + "\n" + String(error));
|
||||
CrashCatcher::Get()->Crash(String(title) + "\n" + String(error));
|
||||
else
|
||||
gCrashCatcher.Crash(error);
|
||||
CrashCatcher::Get()->Crash(error);
|
||||
}
|
||||
|
||||
BFP_EXPORT void BFP_CALLTYPE BfpSystem_GetCommandLine(char* outStr, int* inOutStrSize, BfpSystemResult* outResult)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue