From 904925997a2ca1dfd5db74999f36a39923d0d601 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:11:22 -0500 Subject: [PATCH] Add debugLogFromGfxCallback, refactor displaying fatal error msgbox --- lib/framework/cocoa_wrapper.h | 12 ---- lib/framework/cocoa_wrapper.mm | 23 ------ lib/framework/debug.cpp | 128 +++++++++++++++++++++------------ lib/framework/debug.h | 3 + lib/ivis_opengl/gfx_api_gl.cpp | 2 +- lib/ivis_opengl/gfx_api_vk.cpp | 4 +- 6 files changed, 89 insertions(+), 83 deletions(-) diff --git a/lib/framework/cocoa_wrapper.h b/lib/framework/cocoa_wrapper.h index d4526beb62c..5effb6fb2c7 100644 --- a/lib/framework/cocoa_wrapper.h +++ b/lib/framework/cocoa_wrapper.h @@ -25,18 +25,6 @@ #ifdef WZ_OS_MAC -/*! - * Display an alert dialog. - * This blocks until the dialog is dismissed. - * \param message Summary of the issue - * \param information A more detailed explanation of the issue - * \param style 0 is a warning, 1 is informational, and 2 is critical. (NSAlertStyle) - * \param buttonTitles A null-terminated list of button titles, displayed from right to left. - * \returns The index of the selected button. (0-indexed from leftmost argument, rightmost displayed button.) - */ -int cocoaShowAlert(const char *message, const char *information, unsigned style, - const char *buttonTitles, ...) __attribute__((sentinel)); - bool cocoaSelectFileInFinder(const char *filename); bool cocoaSelectFolderInFinder(const char* path); bool cocoaOpenURL(const char *url); diff --git a/lib/framework/cocoa_wrapper.mm b/lib/framework/cocoa_wrapper.mm index 05230c80a4b..df2a44d0583 100644 --- a/lib/framework/cocoa_wrapper.mm +++ b/lib/framework/cocoa_wrapper.mm @@ -39,29 +39,6 @@ return nsString; } -int cocoaShowAlert(const char *message, const char *information, unsigned style, - const char *buttonTitle, ...) -{ - NSInteger buttonID = -1; - @autoreleasepool { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:nsstringify(message)]; - [alert setInformativeText:nsstringify(information)]; - [alert setAlertStyle:(NSAlertStyle)style]; - - va_list args; - va_start(args, buttonTitle); - const char *currentButtonTitle = buttonTitle; - do { - [alert addButtonWithTitle:nsstringify(currentButtonTitle)]; - } while ((currentButtonTitle = va_arg(args, const char *))); - va_end(args); - - buttonID = [alert runModal]; - } - return static_cast(buttonID - NSAlertFirstButtonReturn); -} - bool cocoaSelectFileInFinder(const char *filename) { if (filename == nullptr) return false; diff --git a/lib/framework/debug.cpp b/lib/framework/debug.cpp index 13ffdc3f460..240d57c20cd 100644 --- a/lib/framework/debug.cpp +++ b/lib/framework/debug.cpp @@ -475,6 +475,88 @@ const char *debugLastError() } } +static void debugDisplayFatalErrorMsgBox(const char* outputLogLine) +{ + if (wzIsFullscreen()) + { + wzChangeWindowMode(WINDOW_MODE::windowed, true); + } +#if defined(WZ_OS_WIN) + char wbuf[MAX_LEN_LOG_LINE+512]; + ssprintf(wbuf, "%s\n\nPlease check the file (%s) in your configuration directory for more details. \ + \nDo not forget to upload the %s file, WZdebuginfo.txt and the warzone2100.rpt files in your bug reports at https://github.com/Warzone2100/warzone2100/issues/new!", outputLogLine, WZ_DBGFile, WZ_DBGFile); + wzDisplayDialog(Dialog_Error, "Warzone has terminated unexpectedly", wbuf); +#elif defined(WZ_OS_MAC) + char wbuf[MAX_LEN_LOG_LINE+128]; + ssprintf(wbuf, "%s\n\nPlease check your logs and attach them along with a bug report. Thanks!", outputLogLine); + size_t clickedIndex = wzDisplayDialogAdvanced(Dialog_Error, "Warzone has quit unexpectedly.", wbuf, {"Show Log Files & Open Bug Reporter", "Ignore"}); + if (clickedIndex == 1) + { + if (!cocoaOpenURL("https://github.com/Warzone2100/warzone2100/issues/new")) + { + wzDisplayDialogAdvanced(Dialog_Error, + "Failed to open URL", + "Could not open URL: https://github.com/Warzone2100/warzone2100/issues/new\nPlease open this URL manually in your web browser.", {"Continue"}); + } + if (strnlen(WZ_DBGFile, sizeof(WZ_DBGFile)/sizeof(WZ_DBGFile[0])) <= 0) + { + wzDisplayDialogAdvanced(Dialog_Error, + "Unable to open debug log.", + "The debug log subsystem has not yet been initialised.", {"Continue"}); + } + else + { + if (!cocoaSelectFileInFinder(WZ_DBGFile)) + { + wzDisplayDialogAdvanced(Dialog_Error, + "Cannot Display Log File", + "The attempt to open a Finder window highlighting the log file from this run failed.", {"Continue"}); + } + } + cocoaOpenUserCrashReportFolder(); + } +#else + wzDisplayDialog(Dialog_Error, "Warzone has terminated unexpectedly", outputLogLine); +#endif +} + +// Special version of _debug that doesn't use any global debug-logging state (or special sauce) *except* the callbackRegistry (via printToDebugCallbacks) +void _debugFromGfxCallback(int line, code_part part, const char *function, const char *str, ...) +{ + char outputBuffer[MAX_LEN_LOG_LINE]; + + time_t rawtime; + struct tm timeinfo = {}; + char ourtime[15]; //HH:MM:SS + time(&rawtime); + timeinfo = getLocalTime(rawtime, true); + strftime(ourtime, 15, "%H:%M:%S", &timeinfo); + + int numPrefixChars = ssprintf(outputBuffer, "%-8s|%s: [%s:%d] ", code_part_names[part], ourtime, function, line); + if (numPrefixChars < 0) + { + // encoding error occurred... + ssprintf(outputBuffer, "%s", "ssprintf failed: encoding error"); + printToDebugCallbacks(outputBuffer, LOG_ERROR); + return; + } + + // Then calculate the remaining length manually and pass the appropriate pointer and length to vsnprintf + size_t remainingLength = MAX_LEN_LOG_LINE - static_cast(numPrefixChars); + char* pStartOutputLineContents = outputBuffer + numPrefixChars; + va_list ap; + va_start(ap, str); + vsnprintf(pStartOutputLineContents, remainingLength, str, ap); + va_end(ap); + + printToDebugCallbacks(outputBuffer, part); + + if (part == LOG_FATAL) + { + debugDisplayFatalErrorMsgBox(pStartOutputLineContents); + } +} + void _debug(int line, code_part part, const char *function, const char *str, ...) { thread_local std::vector outputBuffer(MAX_LEN_LOG_LINE, 0); @@ -578,51 +660,7 @@ void _debug(int line, code_part part, const char *function, const char *str, ... // Throw up a dialog box for users since most don't have a clue to check the dump file for information. Use for (duh) Fatal errors, that force us to terminate the game. if (part == LOG_FATAL) { - if (wzIsFullscreen()) - { - wzChangeWindowMode(WINDOW_MODE::windowed, true); - } -#if defined(WZ_OS_WIN) - char wbuf[MAX_LEN_LOG_LINE+512]; - ssprintf(wbuf, "%s\n\nPlease check the file (%s) in your configuration directory for more details. \ - \nDo not forget to upload the %s file, WZdebuginfo.txt and the warzone2100.rpt files in your bug reports at https://github.com/Warzone2100/warzone2100/issues/new!", currInputBuffer.data(), WZ_DBGFile, WZ_DBGFile); - wzDisplayDialog(Dialog_Error, "Warzone has terminated unexpectedly", wbuf); -#elif defined(WZ_OS_MAC) - char wbuf[MAX_LEN_LOG_LINE+128]; - ssprintf(wbuf, "%s\n\nPlease check your logs and attach them along with a bug report. Thanks!", currInputBuffer.data()); - int clickedIndex = \ - cocoaShowAlert("Warzone has quit unexpectedly.", - wbuf, - 2, "Show Log Files & Open Bug Reporter", "Ignore", NULL); - if (clickedIndex == 0) - { - if (!cocoaOpenURL("https://github.com/Warzone2100/warzone2100/issues/new")) - { - cocoaShowAlert("Failed to open URL", - "Could not open URL: https://github.com/Warzone2100/warzone2100/issues/new\nPlease open this URL manually in your web browser.", - 2, "Continue", NULL); - } - if (strnlen(WZ_DBGFile, sizeof(WZ_DBGFile)/sizeof(WZ_DBGFile[0])) <= 0) - { - cocoaShowAlert("Unable to open debug log.", - "The debug log subsystem has not yet been initialised.", - 2, "Continue", NULL); - } - else - { - if (!cocoaSelectFileInFinder(WZ_DBGFile)) - { - cocoaShowAlert("Cannot Display Log File", - "The attempt to open a Finder window highlighting the log file from this run failed.", - 2, "Continue", NULL); - } - } - cocoaOpenUserCrashReportFolder(); - } -#else - const char *popupBuf = currInputBuffer.data(); - wzDisplayDialog(Dialog_Error, "Warzone has terminated unexpectedly", popupBuf); -#endif + debugDisplayFatalErrorMsgBox(currInputBuffer.data()); } // Throw up a dialog box for windows users since most don't have a clue to check the stderr.txt file for information diff --git a/lib/framework/debug.h b/lib/framework/debug.h index a94a9133c82..7cfbe73012a 100644 --- a/lib/framework/debug.h +++ b/lib/framework/debug.h @@ -283,10 +283,13 @@ bool debug_enable_switch(const char *str); * Only outputs if debugging of part was formerly enabled with debug_enable_switch. */ #define debug(part, ...) do { if (enabled_debug[part]) _debug(__LINE__, part, __FUNCTION__, __VA_ARGS__); } while(0) +#define debugLogFromGfxCallback(part, ...) do { if (enabled_debug[part]) _debugFromGfxCallback(__LINE__, part, __FUNCTION__, __VA_ARGS__); } while(0) #if defined(__MINGW32__) || defined(__MINGW64__) void _debug(int line, code_part part, const char *function, const char *str, ...) WZ_DEBUG_DECL_FORMAT(__MINGW_PRINTF_FORMAT, 4, 5); +void _debugFromGfxCallback(int line, code_part part, const char *function, const char *str, ...) WZ_DEBUG_DECL_FORMAT(__MINGW_PRINTF_FORMAT, 4, 5); #else void _debug(int line, code_part part, const char *function, const char *str, ...) WZ_DEBUG_DECL_FORMAT(printf, 4, 5); +void _debugFromGfxCallback(int line, code_part part, const char *function, const char *str, ...) WZ_DEBUG_DECL_FORMAT(printf, 4, 5); #endif #include diff --git a/lib/ivis_opengl/gfx_api_gl.cpp b/lib/ivis_opengl/gfx_api_gl.cpp index a1cb85a62d3..513c09bce3a 100644 --- a/lib/ivis_opengl/gfx_api_gl.cpp +++ b/lib/ivis_opengl/gfx_api_gl.cpp @@ -3143,7 +3143,7 @@ static void GLAPIENTRY khr_callback(GLenum source, GLenum type, GLuint id, GLenu log_level = LOG_ERROR; } } - debug(log_level, "GL::%s(%s:%s) : %s", cbsource(source), cbtype(type), cbseverity(severity), (message != nullptr) ? message : ""); + debugLogFromGfxCallback(log_level, "GL::%s(%s:%s) : %s", cbsource(source), cbtype(type), cbseverity(severity), (message != nullptr) ? message : ""); } uint32_t gl_context::getSuggestedDefaultDepthBufferResolution() const diff --git a/lib/ivis_opengl/gfx_api_vk.cpp b/lib/ivis_opengl/gfx_api_vk.cpp index 7e5ccbc69a4..5fcf0cca480 100644 --- a/lib/ivis_opengl/gfx_api_vk.cpp +++ b/lib/ivis_opengl/gfx_api_vk.cpp @@ -1065,7 +1065,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL WZDebugReportCallback( logFatal = false; } buf << "[" << pLayerPrefix << "] Code " << msgCode << " : " << pMsg; - debug((logFatal) ? LOG_FATAL : LOG_3D, "%s", buf.str().c_str()); + debugLogFromGfxCallback((logFatal) ? LOG_FATAL : LOG_3D, "%s", buf.str().c_str()); return false; } @@ -1131,7 +1131,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL WZDebugUtilsCallback( buf << "< no callback data? >"; } - debug((logFatal) ? LOG_FATAL : part, "%s", buf.str().c_str()); + debugLogFromGfxCallback((logFatal) ? LOG_FATAL : part, "%s", buf.str().c_str()); return VK_FALSE; }