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:
parent
257fb8c70c
commit
13b2008f79
6
Global.h
6
Global.h
@ -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>
|
||||
|
@ -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()
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user