1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-29 21:56:54 +02:00

Enabled terminate handler and call stack writing on all platforms

Attempt to get a bit more debug info from crashes. VCMI will now:
- use c++ terminate handler on any platform in release builds
- attempt to write call stack to log file using boost::callstack

Since I use std::set_terminate this will only affect c++ exceptions, e.g.
std::runtime_error and will not affect OS signals, e.g. SIGSEGV. Handling
signals is OS-specific and has a lot of limitations that I don't want to
investigate. Besides - most of our crashes are now caused by c++
exceptions.

Haven't tested on other platforms, but should at the very least write
exception information (`e.what()`) for all exceptions and function names
for methods exported from dll's (libvcmi.so & AI's). Possibly more, if
debug information is present.
This commit is contained in:
Ivan Savenko 2024-08-01 21:54:24 +00:00
parent 257fb8c70c
commit 13b2008f79
2 changed files with 43 additions and 25 deletions

View File

@ -102,6 +102,12 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
# define STRONG_INLINE inline
#endif
// Required for building boost::stacktrace on macOS.
// See https://github.com/boostorg/stacktrace/issues/88
#if defined(VCMI_APPLE)
#define _GNU_SOURCE
#endif
#define _USE_MATH_DEFINES
#include <algorithm>

View File

@ -13,6 +13,8 @@
#include "CThreadHelper.h"
#include <boost/stacktrace.hpp>
VCMI_LIB_NAMESPACE_BEGIN
std::mutex CConsoleHandler::smx;
@ -142,6 +144,30 @@ static void createMemoryDump(MINIDUMP_EXCEPTION_INFORMATION * meinfo)
MessageBoxA(0, "VCMI has crashed. We are sorry. File with information about encountered problem has been created.", "VCMI Crashhandler", MB_OK | MB_ICONERROR);
}
LONG WINAPI onUnhandledException(EXCEPTION_POINTERS* exception)
{
logGlobal->error("Disaster happened.");
PEXCEPTION_RECORD einfo = exception->ExceptionRecord;
logGlobal->error("Reason: 0x%x - %s at %04x:%x", einfo->ExceptionCode, exceptionName(einfo->ExceptionCode), exception->ContextRecord->SegCs, (void*)einfo->ExceptionAddress);
if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
logGlobal->error("Attempt to %s 0x%8x", (einfo->ExceptionInformation[0] == 1 ? "write to" : "read from"), (void*)einfo->ExceptionInformation[1]);
}
const DWORD threadId = ::GetCurrentThreadId();
logGlobal->error("Thread ID: %d", threadId);
//exception info to be placed in the dump
MINIDUMP_EXCEPTION_INFORMATION meinfo = {threadId, exception, TRUE};
createMemoryDump(&meinfo);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
[[noreturn]] static void onTerminate()
{
logGlobal->error("Disaster happened.");
@ -166,37 +192,20 @@ static void createMemoryDump(MINIDUMP_EXCEPTION_INFORMATION * meinfo)
logGlobal->error("Reason: unknown exception!");
}
logGlobal->error("Call stack information:");
std::stringstream stream;
stream << boost::stacktrace::stacktrace();
logGlobal->error("%s", stream.str());
#ifdef VCMI_WINDOWS
const DWORD threadId = ::GetCurrentThreadId();
logGlobal->error("Thread ID: %d", threadId);
createMemoryDump(nullptr);
#endif
std::abort();
}
LONG WINAPI onUnhandledException(EXCEPTION_POINTERS* exception)
{
logGlobal->error("Disaster happened.");
PEXCEPTION_RECORD einfo = exception->ExceptionRecord;
logGlobal->error("Reason: 0x%x - %s at %04x:%x", einfo->ExceptionCode, exceptionName(einfo->ExceptionCode), exception->ContextRecord->SegCs, (void*)einfo->ExceptionAddress);
if (einfo->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{
logGlobal->error("Attempt to %s 0x%8x", (einfo->ExceptionInformation[0] == 1 ? "write to" : "read from"), (void*)einfo->ExceptionInformation[1]);
}
const DWORD threadId = ::GetCurrentThreadId();
logGlobal->error("Thread ID: %d", threadId);
//exception info to be placed in the dump
MINIDUMP_EXCEPTION_INFORMATION meinfo = {threadId, exception, TRUE};
createMemoryDump(&meinfo);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
void CConsoleHandler::setColor(EConsoleTextColor::EConsoleTextColor color)
{
TColor colorCode;
@ -289,11 +298,14 @@ CConsoleHandler::CConsoleHandler():
defErrColor = csbi.wAttributes;
#ifndef _DEBUG
SetUnhandledExceptionFilter(onUnhandledException);
std::set_terminate(onTerminate);
#endif
#else
defColor = "\x1b[0m";
#endif
#ifndef _DEBUG
std::set_terminate(onTerminate);
#endif
}
CConsoleHandler::~CConsoleHandler()
{