From 2767faa99be98ed617d2366ad76e558a48226123 Mon Sep 17 00:00:00 2001 From: Xottab-DUTY Date: Mon, 13 May 2019 01:38:29 +0500 Subject: [PATCH] Refactored xrDebug Engine will exit fullscreen mode when crash is happened Under debugger you can press any key except Abort to trigger a debug break when FATAL ERROR was triggered Expanded minidump capabilities.You can use either -full_memory_dump (it can be HUGE) or -detailed_minidump (should be acceptable size) to produce more detailed dump Crash report files folder will be set up right after filesystem initialized Renamed X-Ray Engine to OpenXRay --- src/xrCore/LocatorAPI.cpp | 1 + src/xrCore/xrDebug.cpp | 112 +++++++++++++++++++++-------- src/xrCore/xrDebug.h | 15 +++- src/xrEngine/Device_Initialize.cpp | 2 +- src/xrEngine/Device_create.cpp | 15 ++++ src/xrEngine/device.h | 6 +- 6 files changed, 118 insertions(+), 33 deletions(-) diff --git a/src/xrCore/LocatorAPI.cpp b/src/xrCore/LocatorAPI.cpp index c493ebd88ff..80f2c39ba48 100644 --- a/src/xrCore/LocatorAPI.cpp +++ b/src/xrCore/LocatorAPI.cpp @@ -988,6 +988,7 @@ void CLocatorAPI::_initialize(u32 flags, pcstr target_folder, pcstr fs_name) //----------------------------------------------------------- CreateLog(nullptr != strstr(Core.Params, "-nolog")); + xrDebug::OnFilesystemInitialized(); } void CLocatorAPI::_destroy() diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index fa87c60ab72..f584b7f119e 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -121,11 +121,11 @@ AssertionResult xrDebug::ShowMessage(pcstr title, pcstr message, bool simpleMode #ifdef WINDOWS // because Windows default Message box is fancy HWND hwnd = nullptr; - if (applicationWindow) + if (windowHandler) { SDL_SysWMinfo info; SDL_VERSION(&info.version); - if (SDL_GetWindowWMInfo(applicationWindow, &info)) + if (SDL_GetWindowWMInfo(windowHandler->GetApplicationWindow(), &info)) { switch (info.subsystem) { @@ -156,11 +156,13 @@ AssertionResult xrDebug::ShowMessage(pcstr title, pcstr message, bool simpleMode #else if (simpleMode) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, applicationWindow); + SDL_Window* parent = windowHandler ? windowHandler->GetApplicationWindow() : nullptr; + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, title, message, parent); return AssertionResult::ok; } - messageboxdata.window = applicationWindow; + if (windowHandler) + messageboxdata.window = windowHandler->GetApplicationWindow(); messageboxdata.title = title; messageboxdata.message = message; int button = -1; @@ -200,7 +202,7 @@ SDL_AssertState SDLAssertionHandler(const SDL_AssertData* data, } } -SDL_Window* xrDebug::applicationWindow = nullptr; +IWindowHandler* xrDebug::windowHandler = nullptr; xrDebug::UnhandledExceptionFilter xrDebug::PrevFilter = nullptr; xrDebug::OutOfMemoryCallbackFunc xrDebug::OutOfMemoryCallback = nullptr; xrDebug::CrashHandler xrDebug::OnCrash = nullptr; @@ -521,6 +523,9 @@ AssertionResult xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, cons OnDialog(true); FlushLog(); + if (windowHandler) + windowHandler->DisableFullscreen(); + AssertionResult result = AssertionResult::abort; if (Core.PluginMode) /*result =*/ ShowMessage("X-Ray error", assertionInfo); // Do not assign 'result' @@ -561,6 +566,11 @@ AssertionResult xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, cons if (OnDialog) OnDialog(false); +#ifdef USE_OWN_ERROR_MESSAGE_WINDOW + if (windowHandler) + windowHandler->ResetFullscreen(); +#endif + lock.Leave(); return result; } @@ -573,11 +583,27 @@ AssertionResult xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, cons void xrDebug::DoExit(const std::string& message) { + if (windowHandler) + windowHandler->DisableFullscreen(); + FlushLog(); - ShowMessage("Error", message.c_str()); + + if (IsDebuggerPresent()) + { + const auto result = ShowMessage("Error", message.c_str(), false); + if (result != AssertionResult::abort) + DEBUG_BREAK; + } + else + ShowMessage("Error", message.c_str()); + #if defined(WINDOWS) TerminateProcess(GetCurrentProcess(), 1); #endif + + volatile bool neverTrue = false; // if you're under debugger, + if (neverTrue && windowHandler) // you can jump here manually + windowHandler->ResetFullscreen(); // to reset fullscreen } LPCSTR xrDebug::ErrorToString(long code) @@ -643,12 +669,6 @@ void WINAPI xrDebug::PreErrorHandler(INT_PTR) if (*BugReportFile) BT_AddLogFile(BugReportFile); - string_path dumpPath; - if (FS.path_exist("$app_data_root$")) - FS.update_path(dumpPath, "$app_data_root$", ""); - xr_strcat(dumpPath, "reports"); - - BT_SetReportFilePath(dumpPath); BT_SaveSnapshot(nullptr); #endif } @@ -668,23 +688,27 @@ void xrDebug::SetupExceptionHandler() else BT_SetActivityType(BTA_SAVEREPORT); BT_SetDialogMessage(BTDM_INTRO2, - "This is X-Ray Engine v1.6 crash reporting client. " + "This is OpenXRay crash reporting client. " "To help the development process, " "please Submit Bug or save report and email it manually (button More...)." "\r\n" "Many thanks in advance and sorry for the inconvenience."); BT_SetPreErrHandler(PreErrorHandler, 0); - BT_SetAppName("X-Ray Engine"); + BT_SetAppName("OpenXRay"); BT_SetReportFormat(BTRF_TEXT); BT_SetFlags(BTF_DETAILEDMODE | BTF_ATTACHREPORT); -#ifdef MASTER_GOLD - auto minidumpFlags = MiniDumpFilterMemory | MiniDumpScanMemory; + auto minidumpFlags = MiniDumpWithDataSegs| + MiniDumpWithIndirectlyReferencedMemory | + MiniDumpScanMemory | + MiniDumpWithProcessThreadData | + MiniDumpWithThreadInfo; - if (strstr(commandLine, "-detailed_minidump")) - minidumpFlags = MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory; -#else - const auto minidumpFlags = MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory; + if (strstr(commandLine, "-full_memory_dump")) + minidumpFlags |= MiniDumpWithFullMemory | MiniDumpIgnoreInaccessibleMemory; +#ifdef MASTER_GOLD + else if (!strstr(commandLine, "-detailed_minidump")) + minidumpFlags |= MiniDumpFilterMemory; #endif BT_SetDumpType(minidumpFlags); @@ -693,10 +717,19 @@ void xrDebug::SetupExceptionHandler() #endif } +void xrDebug::OnFilesystemInitialized() +{ + string_path dumpPath; + if (FS.update_path(dumpPath, "$app_data_root$", "reports", false)) + { + BT_SetReportFilePath(dumpPath); + } +} + void xrDebug::FormatLastError(char* buffer, const size_t& bufferSize) { #if defined(WINDOWS) - int lastErr = GetLastError(); + const int lastErr = GetLastError(); if (lastErr == ERROR_SUCCESS) { *buffer = 0; @@ -749,27 +782,50 @@ LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs) } if (shared_str_initialized) FlushLog(); -#ifndef USE_OWN_ERROR_MESSAGE_WINDOW -#ifdef USE_OWN_MINI_DUMP - SaveMiniDump(exPtrs); -#endif -#else + + if (windowHandler) + windowHandler->DisableFullscreen(); + +#ifdef USE_OWN_ERROR_MESSAGE_WINDOW + constexpr pcstr fatalError = "Fatal error"; + + AssertionResult msgRes = AssertionResult::abort; if (!ErrorAfterDialog) { if (OnDialog) OnDialog(true); + constexpr pcstr msg = "Fatal error occurred\n\n" "Press OK to abort program execution"; - ShowMessage("Fatal error", msg); + msgRes = ShowMessage(fatalError, msg); } #endif - ReportFault(exPtrs, 0); + BT_SetUserMessage(fatalError); + BT_SaveSnapshotEx(exPtrs, nullptr); + + const auto reportRes = ReportFault(exPtrs, 0); + if (msgRes != AssertionResult::abort || + reportRes == frrvLaunchDebugger) + { + while (true) + { + if (IsDebuggerPresent()) + DEBUG_BREAK; + } + } + if (PrevFilter) PrevFilter(exPtrs); + #ifdef USE_OWN_ERROR_MESSAGE_WINDOW if (OnDialog) OnDialog(false); #endif + + volatile bool neverTrue = false; // if you're under debugger, + if (neverTrue && windowHandler) // you can manually + windowHandler->ResetFullscreen(); // reset fullscreen + return EXCEPTION_CONTINUE_SEARCH; #else return 0; diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index 49cffeff22c..cff81d7bec7 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -48,6 +48,14 @@ class ErrorLocation } }; +class IWindowHandler +{ +public: + virtual SDL_Window* GetApplicationWindow() = 0; + virtual void DisableFullscreen() = 0; + virtual void ResetFullscreen() = 0; +}; + class XRCORE_API xrDebug { public: @@ -57,7 +65,7 @@ class XRCORE_API xrDebug using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS* exPtrs); private: - static SDL_Window* applicationWindow; + static IWindowHandler* windowHandler; static UnhandledExceptionFilter PrevFilter; static OutOfMemoryCallbackFunc OutOfMemoryCallback; static CrashHandler OnCrash; @@ -70,9 +78,10 @@ class XRCORE_API xrDebug static void Initialize(); static void Destroy(); static void OnThreadSpawn(); + static void OnFilesystemInitialized(); - static SDL_Window* GetApplicationWindow() { return applicationWindow; } - static void SetApplicationWindow(SDL_Window* window) { applicationWindow = window; } + static IWindowHandler* GetWindowHandler() { return windowHandler; } + static void SetWindowHandler(IWindowHandler* handler) { windowHandler = handler; } static OutOfMemoryCallbackFunc GetOutOfMemoryCallback() { return OutOfMemoryCallback; } static void SetOutOfMemoryCallback(OutOfMemoryCallbackFunc cb) { OutOfMemoryCallback = cb; } static CrashHandler GetCrashHandler() { return OnCrash; } diff --git a/src/xrEngine/Device_Initialize.cpp b/src/xrEngine/Device_Initialize.cpp index 3391a1e94ff..580e4574e7f 100644 --- a/src/xrEngine/Device_Initialize.cpp +++ b/src/xrEngine/Device_Initialize.cpp @@ -64,7 +64,7 @@ void CRenderDevice::Initialize() R_ASSERT3(m_sdlWnd, "Unable to create SDL window", SDL_GetError()); SDL_SetWindowHitTest(m_sdlWnd, WindowHitTest, nullptr); SDL_SetWindowMinimumSize(m_sdlWnd, 256, 192); - xrDebug::SetApplicationWindow(m_sdlWnd); + xrDebug::SetWindowHandler(this); } } diff --git a/src/xrEngine/Device_create.cpp b/src/xrEngine/Device_create.cpp index ab15fd2d226..86e9ca12c99 100644 --- a/src/xrEngine/Device_create.cpp +++ b/src/xrEngine/Device_create.cpp @@ -209,3 +209,18 @@ void CRenderDevice::SelectResolution(const bool windowed) dwHeight = psCurrentVidMode[1]; } } + +SDL_Window* CRenderDevice::GetApplicationWindow() +{ + return m_sdlWnd; +} + +void CRenderDevice::DisableFullscreen() +{ + SDL_SetWindowFullscreen(m_sdlWnd, SDL_FALSE); +} + +void CRenderDevice::ResetFullscreen() +{ + UpdateWindowProps(!psDeviceFlags.test(rsFullscreen)); +} diff --git a/src/xrEngine/device.h b/src/xrEngine/device.h index 8cd123e4c24..00aea29bb85 100644 --- a/src/xrEngine/device.h +++ b/src/xrEngine/device.h @@ -132,7 +132,7 @@ class ENGINE_API CRenderDeviceBase : public IRenderDevice, public CRenderDeviceD #pragma pack(pop) // refs -class ENGINE_API CRenderDevice : public CRenderDeviceBase +class ENGINE_API CRenderDevice : public CRenderDeviceBase, public IWindowHandler { public: class ENGINE_API CSecondVPParams //--#SM+#-- +SecondVP+ @@ -279,6 +279,10 @@ class ENGINE_API CRenderDevice : public CRenderDeviceBase virtual const RenderDeviceStatictics& GetStats() const override { return stats; } virtual void DumpStatistics(class IGameFont& font, class IPerformanceAlert* alert) override; + SDL_Window* GetApplicationWindow() override; + void DisableFullscreen() override; + void ResetFullscreen() override; + void time_factor(const float& time_factor) { Timer.time_factor(time_factor);