From 1100b04b59b461f1a2cc3dfe7b53b5473daa7992 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 21 Apr 2021 16:07:48 +0100 Subject: Make Windows go brrrr, not tick. tick. tick. (#5201) * Fixes #5140 --- src/OSSupport/MiniDumpWriter.h | 137 +++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 66 deletions(-) (limited to 'src/OSSupport/MiniDumpWriter.h') diff --git a/src/OSSupport/MiniDumpWriter.h b/src/OSSupport/MiniDumpWriter.h index e5cd1a0ac..c223fa9fb 100644 --- a/src/OSSupport/MiniDumpWriter.h +++ b/src/OSSupport/MiniDumpWriter.h @@ -1,5 +1,11 @@ -#pragma once +// MiniDumpWriter.h + +// 32-bit only: +// When the server crashes, create a "dump file" containing the callstack of each thread and some variables; +// let the user send us that crash file for analysis. + +// This file MUST NOT be included from anywhere other than main.cpp. @@ -18,30 +24,64 @@ enum class MiniDumpFlags #if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC -#include +#include + + + + + +using MiniDumpWriteDumpFunction = decltype(&MiniDumpWriteDump); + +static HINSTANCE m_DbgHelp; +static MiniDumpWriteDumpFunction s_WriteMiniDump; // The function in dbghlp DLL that creates dump files +static wchar_t s_DumpFileName[MAX_PATH]; // Filename of the dump file; hes to be created before the dump handler kicks in +static char s_ExceptionStack[128 * 1024]; // Substitute stack, just in case the handler kicks in because of "insufficient stack space" +static MINIDUMP_TYPE s_DumpFlags = MiniDumpNormal; // By default dump only the stack and some helpers + + + + + +/** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar. +Its purpose is to create the crashdump using the dbghlp DLLs */ +static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) +{ + char * newStack = &s_ExceptionStack[sizeof(s_ExceptionStack) - 1]; + char * oldStack; + + // Use the substitute stack: + _asm + { + mov oldStack, esp + mov esp, newStack + } + + MINIDUMP_EXCEPTION_INFORMATION ExcInformation; + ExcInformation.ThreadId = GetCurrentThreadId(); + ExcInformation.ExceptionPointers = a_ExceptionInfo; + ExcInformation.ClientPointers = 0; + + // Write the dump file: + HANDLE dumpFile = CreateFile(s_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + s_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, s_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); + CloseHandle(dumpFile); + + // Revert to old stack: + _asm + { + mov esp, oldStack + } + + return 0; +} -/** Windows 32-bit stuff: -When the server crashes, create a "dump file" containing the callstack of each thread and some variables; -let the user send us that crash file for analysis */ -class MiniDumpWriter +namespace MiniDumpWriter { - typedef BOOL(WINAPI *pMiniDumpWriteDump)( - HANDLE hProcess, - DWORD ProcessId, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - -public: - - MiniDumpWriter() + static void Register() { // Magic code to produce dump-files on Windows if the server crashes: @@ -51,7 +91,7 @@ public: return; } - s_WriteMiniDump = (pMiniDumpWriteDump)GetProcAddress(m_DbgHelp, "MiniDumpWriteDump"); + s_WriteMiniDump = (MiniDumpWriteDumpFunction)GetProcAddress(m_DbgHelp, "MiniDumpWriteDump"); if (s_WriteMiniDump != nullptr) { ASSERT(swprintf(s_DumpFileName, ARRAYCOUNT(s_DumpFileName), L"crash_mcs_%x.dmp", GetCurrentProcessId()) > 0); @@ -61,7 +101,7 @@ public: // End of dump-file magic } - void AddDumpFlags(const MiniDumpFlags a_Flags) + static void AddDumpFlags(const MiniDumpFlags a_Flags) { switch (a_Flags) { @@ -78,60 +118,25 @@ public: } } - ~MiniDumpWriter() + static void Unregister() { FreeLibrary(m_DbgHelp); } +}; -private: +#else - /** This function gets called just before the "program executed an illegal instruction and will be terminated" or similar. - Its purpose is to create the crashdump using the dbghlp DLLs */ - static LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_ExceptionInfo) +namespace MiniDumpWriter +{ + static void Register() { - char * newStack = &s_ExceptionStack[sizeof(s_ExceptionStack) - 1]; - char * oldStack; - - // Use the substitute stack: - // This code is the reason why we don't support 64-bit (yet) - _asm - { - mov oldStack, esp - mov esp, newStack - } - - MINIDUMP_EXCEPTION_INFORMATION ExcInformation; - ExcInformation.ThreadId = GetCurrentThreadId(); - ExcInformation.ExceptionPointers = a_ExceptionInfo; - ExcInformation.ClientPointers = 0; - - // Write the dump file: - HANDLE dumpFile = CreateFile(s_DumpFileName, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - s_WriteMiniDump(GetCurrentProcess(), GetCurrentProcessId(), dumpFile, s_DumpFlags, (a_ExceptionInfo) ? &ExcInformation : nullptr, nullptr, nullptr); - CloseHandle(dumpFile); - - // Revert to old stack: - _asm - { - mov esp, oldStack - } - - return 0; } - HINSTANCE m_DbgHelp; - - static inline pMiniDumpWriteDump s_WriteMiniDump; // The function in dbghlp DLL that creates dump files - static inline wchar_t s_DumpFileName[MAX_PATH]; // Filename of the dump file; hes to be created before the dump handler kicks in - static inline char s_ExceptionStack[128 * 1024]; // Substitute stack, just in case the handler kicks in because of "insufficient stack space" - static inline MINIDUMP_TYPE s_DumpFlags = MiniDumpNormal; // By default dump only the stack and some helpers -}; - -#else + static void AddDumpFlags(const MiniDumpFlags) + { + } -struct MiniDumpWriter -{ - void AddDumpFlags(const MiniDumpFlags) + static void Unregister() { } }; -- cgit v1.2.3