mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Tier0: crash handler reliability improvements
* Break out of loop when we found and cached the primary graphics device. * Log total and available ram with more accuracy. * (New) log total and available disk space the game is being ran from. * Cache hardware details such as disk space, ram space and graphics device so the crash callback could also use it. * Calculate highest XMM number as unsigned so an ABS call is not needed. * Make the crash callback const. * Provide pointer to instance to the crash callback. * Fix crash callback not running properly; it should always be ran in the context of the current crash, not after. The callback is now ran after the crashmsg application has been started.
This commit is contained in:
parent
7ef0a77bb9
commit
98f4f57afe
@ -38,7 +38,7 @@ static HMODULE s_hModuleHandle = NULL;
|
||||
// UTILITY
|
||||
//#############################################################################
|
||||
|
||||
void Crash_Callback()
|
||||
void Crash_Callback(const CCrashHandler* handler)
|
||||
{
|
||||
// Shutdown SpdLog to flush all buffers.
|
||||
SpdLog_Shutdown();
|
||||
|
@ -4,6 +4,26 @@
|
||||
|
||||
#define CRASHMESSAGE_MSG_EXECUTABLE "bin\\crashmsg.exe"
|
||||
|
||||
class CCrashHandler;
|
||||
typedef void (*CrashCallback_t)(const CCrashHandler* handler);
|
||||
|
||||
struct CrashHardWareInfo_s
|
||||
{
|
||||
CrashHardWareInfo_s()
|
||||
{
|
||||
displayDevice = { sizeof(displayDevice), {0} };
|
||||
memoryStatus = { sizeof(memoryStatus) , {0} };
|
||||
availDiskSpace = 0;
|
||||
totalDiskSpace = 0;
|
||||
}
|
||||
|
||||
DISPLAY_DEVICE displayDevice;
|
||||
MEMORYSTATUSEX memoryStatus;
|
||||
|
||||
size_t totalDiskSpace;
|
||||
size_t availDiskSpace;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -29,6 +49,12 @@ public:
|
||||
|
||||
inline bool IsValid() const { return m_hExceptionHandler != nullptr; };
|
||||
|
||||
inline bool CrashingModuleNameKnown() const { return m_CrashingModule.Length() > 0; }
|
||||
inline const char* GetCrashingModuleName() const { return m_CrashingModule.String(); }
|
||||
|
||||
inline const EXCEPTION_POINTERS* GetExceptionPointers() const { return m_pExceptionPointers; }
|
||||
inline const CrashHardWareInfo_s& GetHardwareInfo() const { return m_HardWareInfo; }
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Formatters:
|
||||
//-------------------------------------------------------------------------
|
||||
@ -46,13 +72,13 @@ public:
|
||||
const char* ExceptionToString(const DWORD nExceptionCode) const;
|
||||
|
||||
void SetExceptionPointers(EXCEPTION_POINTERS* const pExceptionPointers) { m_pExceptionPointers = pExceptionPointers; }
|
||||
void SetCrashCallback(PVOID pCrashCallback) { m_pCrashCallback = pCrashCallback; }
|
||||
void SetCrashCallback(CrashCallback_t pCrashCallback) { m_pCrashCallback = pCrashCallback; }
|
||||
|
||||
void CaptureCallStack();
|
||||
void WriteFile();
|
||||
|
||||
void CreateMessageProcess();
|
||||
void CrashCallback();
|
||||
void CrashCallback() const;
|
||||
|
||||
private:
|
||||
|
||||
@ -83,7 +109,7 @@ private:
|
||||
HMODULE m_ppModuleHandles[MAX_MODULE_HANDLES];
|
||||
|
||||
// Custom crash callback that's called after the logs have been written.
|
||||
PVOID m_pCrashCallback;
|
||||
CrashCallback_t m_pCrashCallback;
|
||||
|
||||
// Current exception handler, only kept here for tracking as we need the
|
||||
// handle if we want to remove this handler.
|
||||
@ -109,6 +135,9 @@ private:
|
||||
|
||||
// Set when crashmsg.exe is created to prevent recursive messages.
|
||||
bool m_bMessageCreated;
|
||||
|
||||
// Cached hardware info this application crashed on.
|
||||
CrashHardWareInfo_s m_HardWareInfo;
|
||||
|
||||
mutable RTL_SRWLOCK m_Lock;
|
||||
};
|
||||
|
@ -171,9 +171,10 @@ void CCrashHandler::FormatSystemInfo()
|
||||
m_Buffer.AppendFormat("\tcpu_model = \"%s\"\n", pi.m_szProcessorBrand);
|
||||
m_Buffer.AppendFormat("\tcpu_speed = %010lld // clock cycles\n", pi.m_Speed);
|
||||
|
||||
DISPLAY_DEVICE& dd = m_HardWareInfo.displayDevice;
|
||||
|
||||
for (DWORD i = 0; ; i++)
|
||||
{
|
||||
DISPLAY_DEVICE dd = { sizeof(dd), {0} };
|
||||
const BOOL f = EnumDisplayDevices(NULL, i, &dd, EDD_GET_DEVICE_INTERFACE_NAME);
|
||||
|
||||
if (!f)
|
||||
@ -185,16 +186,28 @@ void CCrashHandler::FormatSystemInfo()
|
||||
{
|
||||
m_Buffer.AppendFormat("\tgpu_model = \"%s\"\n", dd.DeviceString);
|
||||
m_Buffer.AppendFormat("\tgpu_flags = 0x%08X // primary device\n", dd.StateFlags);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MEMORYSTATUSEX statex{};
|
||||
statex.dwLength = sizeof(statex);
|
||||
MEMORYSTATUSEX& statex = m_HardWareInfo.memoryStatus;
|
||||
|
||||
if (GlobalMemoryStatusEx(&statex))
|
||||
{
|
||||
m_Buffer.AppendFormat("\tram_total = [%010d, %010d] // physical/virtual (MiB)\n", (statex.ullTotalPhys / 1024) / 1024, (statex.ullTotalVirtual / 1024) / 1024);
|
||||
m_Buffer.AppendFormat("\tram_avail = [%010d, %010d] // physical/virtual (MiB)\n", (statex.ullAvailPhys / 1024) / 1024, (statex.ullAvailVirtual / 1024) / 1024);
|
||||
m_Buffer.AppendFormat("\tram_total = [%.2lf, %.2lf] // physical/virtual (MiB)\n", (f64)(statex.ullTotalPhys / (1024.0 * 1024.0)), (f64)(statex.ullTotalVirtual / (1024.0 * 1024.0)));
|
||||
m_Buffer.AppendFormat("\tram_avail = [%.2lf, %.2lf] // physical/virtual (MiB)\n", (f64)(statex.ullAvailPhys / (1024.0 * 1024.0)), (f64)(statex.ullAvailVirtual / (1024.0 * 1024.0)));
|
||||
}
|
||||
|
||||
DWORD sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;
|
||||
|
||||
if (GetDiskFreeSpaceA(NULL, §orsPerCluster, &bytesPerSector, &freeClusters, &totalClusters))
|
||||
{
|
||||
m_HardWareInfo.totalDiskSpace = (u64)totalClusters * sectorsPerCluster * bytesPerSector;
|
||||
m_HardWareInfo.availDiskSpace = (u64)freeClusters * sectorsPerCluster * bytesPerSector;
|
||||
|
||||
m_Buffer.AppendFormat("\tdsk_total = %.2lf // (MiB)\n", (f64)(m_HardWareInfo.totalDiskSpace / (1024.0 * 1024.0)));
|
||||
m_Buffer.AppendFormat("\tdsk_avail = %.2lf // (MiB)\n", (f64)(m_HardWareInfo.availDiskSpace / (1024.0 * 1024.0)));
|
||||
}
|
||||
|
||||
m_Buffer.Append("}\n");
|
||||
@ -366,7 +379,7 @@ void CCrashHandler::FormatFPU(const char* const pszRegister, const M128A* const
|
||||
*reinterpret_cast<const FLOAT*>(&nVec[2]),
|
||||
*reinterpret_cast<const FLOAT*>(&nVec[3]));
|
||||
|
||||
const LONG nHighest = abs(LONG(*MaxElementABS(std::begin(nVec), std::end(nVec))));
|
||||
const DWORD nHighest = *MaxElementABS(std::begin(nVec), std::end(nVec));
|
||||
|
||||
if (nHighest >= 1000000)
|
||||
{
|
||||
@ -531,11 +544,11 @@ void CCrashHandler::CreateMessageProcess()
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: calls the crash callback
|
||||
//-----------------------------------------------------------------------------
|
||||
void CCrashHandler::CrashCallback()
|
||||
void CCrashHandler::CrashCallback() const
|
||||
{
|
||||
if (m_pCrashCallback)
|
||||
{
|
||||
((void(*)(void))m_pCrashCallback)();
|
||||
m_pCrashCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -548,11 +561,9 @@ long __stdcall BottomLevelExceptionFilter(EXCEPTION_POINTERS* const pExceptionIn
|
||||
{
|
||||
g_CrashHandler.Start();
|
||||
|
||||
// If the exception couldn't be handled, run the crash callback and
|
||||
// terminate the process
|
||||
// If the exception couldn't be handled, terminate the process
|
||||
if (g_CrashHandler.GetExit())
|
||||
{
|
||||
g_CrashHandler.CrashCallback();
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
@ -590,6 +601,9 @@ long __stdcall BottomLevelExceptionFilter(EXCEPTION_POINTERS* const pExceptionIn
|
||||
// Display the message to the user.
|
||||
g_CrashHandler.CreateMessageProcess();
|
||||
|
||||
// Run the crash callback
|
||||
g_CrashHandler.CrashCallback();
|
||||
|
||||
// End it here, the next recursive call terminates the process.
|
||||
g_CrashHandler.End();
|
||||
|
||||
@ -625,7 +639,6 @@ void CCrashHandler::Reset()
|
||||
m_Buffer.Clear();
|
||||
m_CrashingModule.Clear();
|
||||
m_MessageCmdLine.Clear();
|
||||
|
||||
m_nCrashMsgFlags = 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user