Skip to content

Commit

Permalink
Add debugLogFromGfxCallback, refactor displaying fatal error msgbox
Browse files Browse the repository at this point in the history
  • Loading branch information
past-due committed Nov 28, 2023
1 parent 00bacce commit a86f856
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 83 deletions.
12 changes: 0 additions & 12 deletions lib/framework/cocoa_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
23 changes: 0 additions & 23 deletions lib/framework/cocoa_wrapper.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>(buttonID - NSAlertFirstButtonReturn);
}

bool cocoaSelectFileInFinder(const char *filename)
{
if (filename == nullptr) return false;
Expand Down
128 changes: 83 additions & 45 deletions lib/framework/debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<size_t>(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<char> outputBuffer(MAX_LEN_LOG_LINE, 0);
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions lib/framework/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <string>
Expand Down
2 changes: 1 addition & 1 deletion lib/ivis_opengl/gfx_api_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/ivis_opengl/gfx_api_vk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit a86f856

Please sign in to comment.