Skip to content

Commit

Permalink
Refactored code
Browse files Browse the repository at this point in the history
  • Loading branch information
TracerDS committed Jan 11, 2024
1 parent 8dd9349 commit e2c1789
Show file tree
Hide file tree
Showing 33 changed files with 1,803 additions and 1,837 deletions.
197 changes: 101 additions & 96 deletions Server/core/CCrashHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
#include "StdInc.h"
#include "CCrashHandler.h"
#include "version.h"
#ifdef WIN32
#ifdef _WIN32
#include "CExceptionInformation_Impl.h"
#else
#include <execinfo.h>
#endif

// clang-format off
#ifndef WIN32
#ifndef _WIN32
#if __has_include(<ncursesw/curses.h>)
#include <ncursesw/curses.h>
#else
Expand All @@ -45,7 +45,7 @@ static SString ms_strDumpPathFilename;

static SString ms_strDumpPath;

#ifdef WIN32
#ifdef _WIN32
#include <ctime>
#include <tchar.h>
#include <dbghelp.h>
Expand All @@ -64,7 +64,7 @@ void CCrashHandler::Init(const SString& strInServerPath)
ms_strDumpPath = PathJoin(strServerPath, SERVER_DUMP_PATH);

// Set a global filter
#ifdef WIN32
#ifdef _WIN32
SetCrashHandlerFilter(HandleExceptionGlobal);
#else

Expand All @@ -88,7 +88,7 @@ void CCrashHandler::Init(const SString& strInServerPath)
#endif
}

#ifndef WIN32
#ifndef _WIN32

// Save basic backtrace info into a file. Forced inline to avoid backtrace pollution
inline __attribute__((always_inline)) static void SaveBacktraceSummary()
Expand Down Expand Up @@ -212,103 +212,108 @@ void CCrashHandler::DumpMiniDump(_EXCEPTION_POINTERS* pException, CExceptionInfo
}

// We could load a dll?
if (hDll)
if (!hDll)
return;

// Grab the MiniDumpWriteDump proc address
MINIDUMPWRITEDUMP pDump = reinterpret_cast<MINIDUMPWRITEDUMP>(GetProcAddress(hDll, "MiniDumpWriteDump"));
if (!pDump)
{
// Grab the MiniDumpWriteDump proc address
MINIDUMPWRITEDUMP pDump = reinterpret_cast<MINIDUMPWRITEDUMP>(GetProcAddress(hDll, "MiniDumpWriteDump"));
if (pDump)
{
// Grab the current time
// Ask windows for the system time.
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);

// Create the dump directory
CreateDirectory(ms_strDumpPath, 0);
CreateDirectory(PathJoin(ms_strDumpPath, "private"), 0);

SString strModuleName = pExceptionInformation->GetModuleBaseName();
strModuleName = strModuleName.ReplaceI(".dll", "").Replace(".exe", "").Replace("_", "").Replace(".", "").Replace("-", "");
if (strModuleName.length() == 0)
strModuleName = "unknown";

#ifdef _WIN64
strModuleName += "64";
#endif
// Free the DLL again
FreeLibrary(hDll);
return;
}

SString strFilename("server_%s_%s_%08x_%x_%04d%02d%02d_%02d%02d.dmp", MTA_DM_BUILDTAG_LONG, strModuleName.c_str(),
pExceptionInformation->GetAddressModuleOffset(), pExceptionInformation->GetCode() & 0xffff, SystemTime.wYear, SystemTime.wMonth,
SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute);

SString strFinalDumpPathFilename = PathJoin(ms_strDumpPath, "private", strFilename);

// Create the file
HANDLE hFile = CreateFile(strFinalDumpPathFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// Create an exception information struct
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = GetCurrentThreadId();
ExInfo.ExceptionPointers = pException;
ExInfo.ClientPointers = FALSE;

// Write the dump
pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)(MiniDumpNormal | MiniDumpWithIndirectlyReferencedMemory), &ExInfo,
NULL, NULL);

// Close the dumpfile
CloseHandle(hFile);

FileSave(PathJoin(ms_strDumpPath, "server_pending_upload_filename"), strFinalDumpPathFilename);
}

// Write a log with the generic exception information
FILE* pFile = File::Fopen(PathJoin(ms_strDumpPath, "server_pending_upload.log"), "a+");
if (pFile)
{
// Header
fprintf(pFile, "%s", "** -- Unhandled exception -- **\n\n");

// Write the time
time_t timeTemp;
time(&timeTemp);

SString strMTAVersionFull = SString("%s", MTA_DM_BUILDTAG_LONG);

SString strInfo;
strInfo += SString("Version = %s\n", strMTAVersionFull.c_str());
strInfo += SString("Time = %s", ctime(&timeTemp));

strInfo += SString("Module = %s\n", pExceptionInformation->GetModulePathName());

// Write the basic exception information
strInfo += SString("Code = 0x%08X\n", pExceptionInformation->GetCode());
strInfo += SString("Offset = 0x%08X\n\n", pExceptionInformation->GetAddressModuleOffset());

// Write the register info
strInfo += SString(
"EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
"EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"
"CS=%04X DS=%04X SS=%04X ES=%04X "
"FS=%04X GS=%04X\n\n",
pExceptionInformation->GetEAX(), pExceptionInformation->GetEBX(), pExceptionInformation->GetECX(), pExceptionInformation->GetEDX(),
pExceptionInformation->GetESI(), pExceptionInformation->GetEDI(), pExceptionInformation->GetEBP(), pExceptionInformation->GetESP(),
pExceptionInformation->GetEIP(), pExceptionInformation->GetEFlags(), pExceptionInformation->GetCS(), pExceptionInformation->GetDS(),
pExceptionInformation->GetSS(), pExceptionInformation->GetES(), pExceptionInformation->GetFS(), pExceptionInformation->GetGS());

fprintf(pFile, "%s", strInfo.c_str());

// End of unhandled exception
fprintf(pFile, "%s", "** -- End of unhandled exception -- **\n\n\n");

// Close the file
fclose(pFile);
}
}
// Grab the current time
// Ask windows for the system time.
SYSTEMTIME SystemTime;
GetLocalTime(&SystemTime);

// Create the dump directory
CreateDirectory(ms_strDumpPath, 0);
CreateDirectory(PathJoin(ms_strDumpPath, "private"), 0);

SString strModuleName = pExceptionInformation->GetModuleBaseName();
strModuleName = strModuleName.ReplaceI(".dll", "").Replace(".exe", "").Replace("_", "").Replace(".", "").Replace("-", "");
if (strModuleName.length() == 0)
strModuleName = "unknown";

#ifdef _WIN64
strModuleName += "64";
#endif

SString strFilename("server_%s_%s_%08x_%x_%04d%02d%02d_%02d%02d.dmp", MTA_DM_BUILDTAG_LONG, strModuleName.c_str(),
pExceptionInformation->GetAddressModuleOffset(), pExceptionInformation->GetCode() & 0xffff, SystemTime.wYear, SystemTime.wMonth,
SystemTime.wDay, SystemTime.wHour, SystemTime.wMinute);

SString strFinalDumpPathFilename = PathJoin(ms_strDumpPath, "private", strFilename);

// Create the file
HANDLE hFile = CreateFile(strFinalDumpPathFilename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// Create an exception information struct
_MINIDUMP_EXCEPTION_INFORMATION ExInfo;
ExInfo.ThreadId = GetCurrentThreadId();
ExInfo.ExceptionPointers = pException;
ExInfo.ClientPointers = FALSE;

// Write the dump
pDump(GetCurrentProcess(), GetCurrentProcessId(), hFile, (MINIDUMP_TYPE)(MiniDumpNormal | MiniDumpWithIndirectlyReferencedMemory), &ExInfo,
NULL, NULL);

// Close the dumpfile
CloseHandle(hFile);

FileSave(PathJoin(ms_strDumpPath, "server_pending_upload_filename"), strFinalDumpPathFilename);
}

// Write a log with the generic exception information
FILE* pFile = File::Fopen(PathJoin(ms_strDumpPath, "server_pending_upload.log"), "a+");
if (!pFile)
{
// Free the DLL again
FreeLibrary(hDll);
return;
}

// Header
fprintf(pFile, "%s", "** -- Unhandled exception -- **\n\n");

// Write the time
time_t timeTemp;
time(&timeTemp);

SString strMTAVersionFull = SString("%s", MTA_DM_BUILDTAG_LONG);

SString strInfo;
strInfo += SString("Version = %s\n", strMTAVersionFull.c_str());
strInfo += SString("Time = %s", ctime(&timeTemp));

strInfo += SString("Module = %s\n", pExceptionInformation->GetModulePathName());

// Write the basic exception information
strInfo += SString("Code = 0x%08X\n", pExceptionInformation->GetCode());
strInfo += SString("Offset = 0x%08X\n\n", pExceptionInformation->GetAddressModuleOffset());

// Write the register info
strInfo += SString(
"EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X\n"
"EDI=%08X EBP=%08X ESP=%08X EIP=%08X FLG=%08X\n"
"CS=%04X DS=%04X SS=%04X ES=%04X "
"FS=%04X GS=%04X\n\n",
pExceptionInformation->GetEAX(), pExceptionInformation->GetEBX(), pExceptionInformation->GetECX(), pExceptionInformation->GetEDX(),
pExceptionInformation->GetESI(), pExceptionInformation->GetEDI(), pExceptionInformation->GetEBP(), pExceptionInformation->GetESP(),
pExceptionInformation->GetEIP(), pExceptionInformation->GetEFlags(), pExceptionInformation->GetCS(), pExceptionInformation->GetDS(),
pExceptionInformation->GetSS(), pExceptionInformation->GetES(), pExceptionInformation->GetFS(), pExceptionInformation->GetGS());

fprintf(pFile, "%s", strInfo.c_str());

// End of unhandled exception
fprintf(pFile, "%s", "** -- End of unhandled exception -- **\n\n\n");

// Close the file
fclose(pFile);
}

void CCrashHandler::RunErrorTool()
Expand Down
4 changes: 2 additions & 2 deletions Server/core/CCrashHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "CCrashHandlerAPI.h"

#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#else
#include <signal.h>
Expand All @@ -27,7 +27,7 @@ class CCrashHandler
static void Init(const SString& strServerPath);

private:
#ifdef WIN32
#ifdef _WIN32

static long WINAPI HandleExceptionGlobal(_EXCEPTION_POINTERS* pException);
static void DumpMiniDump(_EXCEPTION_POINTERS* pException, CExceptionInformation* pExceptionInformation);
Expand Down
81 changes: 39 additions & 42 deletions Server/core/CCrashHandlerAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ CONDITIONAL COMPILATION :

#include "StdInc.h"
#include "CCrashHandlerAPI.h"
#ifdef WIN32
#ifdef _WIN32

#ifdef _M_IX86
#include <SharedUtil.Detours.h>
Expand All @@ -50,20 +50,18 @@ LONG __stdcall CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pExPtrs);
Destructor Class
//////////////////////////////////////////////////////////////////////*/
// See the note in MEMDUMPVALIDATOR.CPP about automatic classes.
// Turn off warning : initializers put in library initialization area
#pragma warning (disable : 4073)
#pragma init_seg(lib)
class CleanUpCrashHandler
{
public:
CleanUpCrashHandler() {}
~CleanUpCrashHandler()
{
if (NULL != g_pfnOrigFilt)
{
// Restore the original unhandled exception filter.
SetUnhandledExceptionFilter(g_pfnOrigFilt);
}
if (!g_pfnOrigFilt)
return;

// Restore the original unhandled exception filter.
SetUnhandledExceptionFilter(g_pfnOrigFilt);
}
};

Expand All @@ -77,48 +75,47 @@ static CleanUpCrashHandler g_cBeforeAndAfter;
BOOL __stdcall SetCrashHandlerFilter(PFNCHFILTFN pFn)
{
// A NULL parameter unhooks the callback.
if (NULL == pFn)
if (!pFn)
{
if (NULL != g_pfnOrigFilt)
if (g_pfnOrigFilt)
{
// Restore the original unhandled exception filter.
SetUnhandledExceptionFilter(g_pfnOrigFilt);
g_pfnOrigFilt = NULL;
g_pfnCallBack = NULL;
g_pfnOrigFilt = nullptr;
g_pfnCallBack = nullptr;
}
return true;
}
else
{
if (TRUE == IsBadCodePtr((FARPROC)pFn))
{
return (FALSE);
}
g_pfnCallBack = pFn;

// If a custom crash handler isn't already in use, enable
// CrashHandlerExceptionFilter and save the original unhandled
// exception filter.
if (NULL == g_pfnOrigFilt)
{
g_pfnOrigFilt = SetUnhandledExceptionFilter(CrashHandlerExceptionFilter);
if (IsBadCodePtr((FARPROC)pFn))
return false;

g_pfnCallBack = pFn;

// If a custom crash handler isn't already in use, enable
// CrashHandlerExceptionFilter and save the original unhandled
// exception filter.
if (g_pfnOrigFilt)
return true;

g_pfnOrigFilt = SetUnhandledExceptionFilter(CrashHandlerExceptionFilter);

#ifdef _M_IX86
// Stop the OS from turning off our handler
// Ref: http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI * RedirectedSetUnhandledExceptionFilter)
(LPTOP_LEVEL_EXCEPTION_FILTER) = [](LPTOP_LEVEL_EXCEPTION_FILTER /*ExceptionInfo*/) -> LPTOP_LEVEL_EXCEPTION_FILTER {
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
// our handler will not get removed.
return 0;
};
static_assert(std::is_same_v<decltype(RedirectedSetUnhandledExceptionFilter), decltype(&SetUnhandledExceptionFilter)>,
"invalid type of RedirectedSetUnhandledExceptionFilter");

DetourLibraryFunction("kernel32.dll", "SetUnhandledExceptionFilter", RedirectedSetUnhandledExceptionFilter);
// Stop the OS from turning off our handler
// Ref: http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
LPTOP_LEVEL_EXCEPTION_FILTER(WINAPI * RedirectedSetUnhandledExceptionFilter)
(LPTOP_LEVEL_EXCEPTION_FILTER) = [](LPTOP_LEVEL_EXCEPTION_FILTER /*ExceptionInfo*/) -> LPTOP_LEVEL_EXCEPTION_FILTER {
// When the CRT calls SetUnhandledExceptionFilter with NULL parameter
// our handler will not get removed.
return 0;
};
static_assert(std::is_same_v<decltype(RedirectedSetUnhandledExceptionFilter), decltype(&SetUnhandledExceptionFilter)>,
"invalid type of RedirectedSetUnhandledExceptionFilter");

DetourLibraryFunction("kernel32.dll", "SetUnhandledExceptionFilter", RedirectedSetUnhandledExceptionFilter);
#endif
}
}
return (TRUE);

return true;
}

LONG __stdcall CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pExPtrs)
Expand Down Expand Up @@ -154,15 +151,15 @@ LONG __stdcall CrashHandlerExceptionFilter(EXCEPTION_POINTERS* pExPtrs)

__try
{
if (NULL != g_pfnCallBack)
if (g_pfnCallBack)
{
// Check that the crash handler still exists in memory
// before I call it. The user might have forgotten to
// unregister, and the crash handler is invalid because
// it got unloaded. If some other function loaded
// back into the same address, however, there isn't much
// I can do.
if (FALSE == IsBadCodePtr((FARPROC)g_pfnCallBack))
if (!IsBadCodePtr((FARPROC)g_pfnCallBack))
{
lRet = g_pfnCallBack(pExPtrs);
}
Expand Down
Loading

0 comments on commit e2c1789

Please sign in to comment.