|
@@ -23,6 +23,15 @@ DLL_LINKAGE CConsoleHandler * console = nullptr;
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|
|
|
|
|
|
+#if defined(NDEBUG) && !defined(VCMI_ANDROID)
|
|
|
+#define USE_ON_TERMINATE
|
|
|
+#endif
|
|
|
+
|
|
|
+#if defined(NDEBUG) && defined(VCMI_WINDOWS)
|
|
|
+#define USE_UNHANDLED_EXCEPTION_FILTER
|
|
|
+#define CREATE_MEMORY_DUMP
|
|
|
+#endif
|
|
|
+
|
|
|
#ifndef VCMI_WINDOWS
|
|
|
using TColor = std::string;
|
|
|
#define CONSOLE_GREEN "\x1b[1;32m"
|
|
@@ -57,27 +66,44 @@ static TColor defColor;
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
|
-#ifdef VCMI_WINDOWS
|
|
|
+#ifdef CREATE_MEMORY_DUMP
|
|
|
|
|
|
-void printWinError()
|
|
|
+static void createMemoryDump(MINIDUMP_EXCEPTION_INFORMATION * meinfo)
|
|
|
{
|
|
|
- //Get error code
|
|
|
- int error = GetLastError();
|
|
|
- if(!error)
|
|
|
+ //create file where dump will be placed
|
|
|
+ char *mname = nullptr;
|
|
|
+ char buffer[MAX_PATH + 1];
|
|
|
+ HMODULE hModule = nullptr;
|
|
|
+ GetModuleFileNameA(hModule, buffer, MAX_PATH);
|
|
|
+ mname = strrchr(buffer, '\\');
|
|
|
+ if (mname != nullptr)
|
|
|
+ mname++;
|
|
|
+ else
|
|
|
+ mname = buffer;
|
|
|
+
|
|
|
+ strcat(mname, "_crashinfo.dmp");
|
|
|
+ HANDLE dfile = CreateFileA(mname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
|
|
+ logGlobal->error("Crash info will be put in %s", mname);
|
|
|
+
|
|
|
+ auto dumpType = MiniDumpWithDataSegs;
|
|
|
+
|
|
|
+ if(settings["general"]["extraDump"].Bool())
|
|
|
{
|
|
|
- logGlobal->error("No Win error information set.");
|
|
|
- return;
|
|
|
+ dumpType = (MINIDUMP_TYPE)(
|
|
|
+ MiniDumpWithFullMemory
|
|
|
+ | MiniDumpWithFullMemoryInfo
|
|
|
+ | MiniDumpWithHandleData
|
|
|
+ | MiniDumpWithUnloadedModules
|
|
|
+ | MiniDumpWithThreadInfo);
|
|
|
}
|
|
|
- logGlobal->error("Error %d encountered:", error);
|
|
|
-
|
|
|
- //Get error description
|
|
|
- char* pTemp = nullptr;
|
|
|
- FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
- nullptr, error, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (LPSTR)&pTemp, 1, nullptr);
|
|
|
- logGlobal->error(pTemp);
|
|
|
- LocalFree( pTemp );
|
|
|
+
|
|
|
+ MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dfile, dumpType, meinfo, nullptr, nullptr);
|
|
|
+ MessageBoxA(0, "VCMI has crashed. We are sorry. File with information about encountered problem has been created.", "VCMI Crashhandler", MB_OK | MB_ICONERROR);
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef USE_UNHANDLED_EXCEPTION_FILTER
|
|
|
const char* exceptionName(DWORD exc)
|
|
|
{
|
|
|
#define EXC_CASE(EXC) case EXCEPTION_##EXC : return "EXCEPTION_" #EXC
|
|
@@ -111,39 +137,6 @@ const char* exceptionName(DWORD exc)
|
|
|
#undef EXC_CASE
|
|
|
}
|
|
|
|
|
|
-static void createMemoryDump(MINIDUMP_EXCEPTION_INFORMATION * meinfo)
|
|
|
-{
|
|
|
- //create file where dump will be placed
|
|
|
- char *mname = nullptr;
|
|
|
- char buffer[MAX_PATH + 1];
|
|
|
- HMODULE hModule = nullptr;
|
|
|
- GetModuleFileNameA(hModule, buffer, MAX_PATH);
|
|
|
- mname = strrchr(buffer, '\\');
|
|
|
- if (mname != nullptr)
|
|
|
- mname++;
|
|
|
- else
|
|
|
- mname = buffer;
|
|
|
-
|
|
|
- strcat(mname, "_crashinfo.dmp");
|
|
|
- HANDLE dfile = CreateFileA(mname, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
|
|
|
- logGlobal->error("Crash info will be put in %s", mname);
|
|
|
-
|
|
|
- auto dumpType = MiniDumpWithDataSegs;
|
|
|
-
|
|
|
- if(settings["general"]["extraDump"].Bool())
|
|
|
- {
|
|
|
- dumpType = (MINIDUMP_TYPE)(
|
|
|
- MiniDumpWithFullMemory
|
|
|
- | MiniDumpWithFullMemoryInfo
|
|
|
- | MiniDumpWithHandleData
|
|
|
- | MiniDumpWithUnloadedModules
|
|
|
- | MiniDumpWithThreadInfo);
|
|
|
- }
|
|
|
-
|
|
|
- MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), dfile, dumpType, meinfo, nullptr, nullptr);
|
|
|
- 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.");
|
|
@@ -161,14 +154,15 @@ LONG WINAPI onUnhandledException(EXCEPTION_POINTERS* exception)
|
|
|
//exception info to be placed in the dump
|
|
|
MINIDUMP_EXCEPTION_INFORMATION meinfo = {threadId, exception, TRUE};
|
|
|
|
|
|
+#ifdef CREATE_MEMORY_DUMP
|
|
|
createMemoryDump(&meinfo);
|
|
|
+#endif
|
|
|
|
|
|
return EXCEPTION_EXECUTE_HANDLER;
|
|
|
}
|
|
|
-
|
|
|
#endif
|
|
|
|
|
|
-#ifdef NDEBUG
|
|
|
+#ifdef USE_ON_TERMINATE
|
|
|
[[noreturn]] static void onTerminate()
|
|
|
{
|
|
|
logGlobal->error("Disaster happened.");
|
|
@@ -198,7 +192,7 @@ LONG WINAPI onUnhandledException(EXCEPTION_POINTERS* exception)
|
|
|
stream << boost::stacktrace::stacktrace();
|
|
|
logGlobal->error("%s", stream.str());
|
|
|
|
|
|
-#ifdef VCMI_WINDOWS
|
|
|
+#ifdef CREATE_MEMORY_DUMP
|
|
|
const DWORD threadId = ::GetCurrentThreadId();
|
|
|
logGlobal->error("Thread ID: %d", threadId);
|
|
|
|
|
@@ -298,19 +292,19 @@ CConsoleHandler::CConsoleHandler():
|
|
|
|
|
|
GetConsoleScreenBufferInfo(handleErr, &csbi);
|
|
|
defErrColor = csbi.wAttributes;
|
|
|
-#ifdef NDEBUG
|
|
|
-#ifndef VCMI_ANDROID
|
|
|
- SetUnhandledExceptionFilter(onUnhandledException);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
#else
|
|
|
defColor = "\x1b[0m";
|
|
|
#endif
|
|
|
|
|
|
-#ifdef NDEBUG
|
|
|
+#ifdef USE_UNHANDLED_EXCEPTION_FILTER
|
|
|
+ SetUnhandledExceptionFilter(onUnhandledException);
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef USE_ON_TERMINATE
|
|
|
std::set_terminate(onTerminate);
|
|
|
#endif
|
|
|
}
|
|
|
+
|
|
|
CConsoleHandler::~CConsoleHandler()
|
|
|
{
|
|
|
logGlobal->info("Killing console...");
|