2020-07-22 19:34:43 -04:00
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
// 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.
|
2020-07-22 19:34:43 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Flags to control minidump contents on supported platforms. */
|
|
|
|
enum class MiniDumpFlags
|
|
|
|
{
|
|
|
|
WithDataSegments,
|
|
|
|
WithFullMemory
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32) && !defined(_WIN64) && defined(_MSC_VER) // 32-bit Windows app compiled in MSVC
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
#include <DbgHelp.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2020-07-22 19:34:43 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
namespace MiniDumpWriter
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
2021-04-21 11:07:48 -04:00
|
|
|
static void Register()
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
|
|
|
// Magic code to produce dump-files on Windows if the server crashes:
|
|
|
|
|
|
|
|
m_DbgHelp = LoadLibrary(L"DBGHELP.DLL");
|
|
|
|
if (m_DbgHelp == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
s_WriteMiniDump = (MiniDumpWriteDumpFunction)GetProcAddress(m_DbgHelp, "MiniDumpWriteDump");
|
2020-07-22 19:34:43 -04:00
|
|
|
if (s_WriteMiniDump != nullptr)
|
|
|
|
{
|
|
|
|
ASSERT(swprintf(s_DumpFileName, ARRAYCOUNT(s_DumpFileName), L"crash_mcs_%x.dmp", GetCurrentProcessId()) > 0);
|
|
|
|
SetUnhandledExceptionFilter(LastChanceExceptionFilter);
|
|
|
|
}
|
|
|
|
|
|
|
|
// End of dump-file magic
|
|
|
|
}
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
static void AddDumpFlags(const MiniDumpFlags a_Flags)
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
|
|
|
switch (a_Flags)
|
|
|
|
{
|
|
|
|
case MiniDumpFlags::WithDataSegments:
|
|
|
|
{
|
|
|
|
s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithDataSegs);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case MiniDumpFlags::WithFullMemory:
|
|
|
|
{
|
|
|
|
s_DumpFlags = static_cast<MINIDUMP_TYPE>(s_DumpFlags | MINIDUMP_TYPE::MiniDumpWithFullMemory);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
static void Unregister()
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
|
|
|
FreeLibrary(m_DbgHelp);
|
|
|
|
}
|
2021-04-21 11:07:48 -04:00
|
|
|
};
|
2020-07-22 19:34:43 -04:00
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
#else
|
2020-07-22 19:34:43 -04:00
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
namespace MiniDumpWriter
|
|
|
|
{
|
|
|
|
static void Register()
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
static void AddDumpFlags(const MiniDumpFlags)
|
|
|
|
{
|
|
|
|
}
|
2020-07-22 19:34:43 -04:00
|
|
|
|
2021-04-21 11:07:48 -04:00
|
|
|
static void Unregister()
|
2020-07-22 19:34:43 -04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|