From 125ce7137987ec91b931b4fb97d9c3c7af88c377 Mon Sep 17 00:00:00 2001 From: Anonymous Maarten Date: Wed, 7 Aug 2024 23:49:02 +0200 Subject: [PATCH] SDL_Log: avoid sending text to the debug stream twice When debugging a GUI application in Visual Studio, text printed with fprintf(stderr) will also be sent to the debug stream. When buiding SDL with SDL_LIBC=ON, this patch makes logging skip OutputDebugString and rely on fprintf(stderr) to send the text to the debugger. --- src/SDL_log.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/SDL_log.c b/src/SDL_log.c index 2b2680f5f..000c90e64 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -510,9 +510,14 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S } } -#if defined(SDL_PLATFORM_WIN32) && !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) -/* Flag tracking the attachment of the console: 0=unattached, 1=attached to a console, 2=attached to a file, -1=error */ -static int consoleAttached = 0; +#if defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) +enum { + CONSOLE_UNATTACHED = 0, + CONSOLE_ATTACHED_CONSOLE = 1, + CONSOLE_ATTACHED_FILE = 2, + CONSOLE_ATTACHED_MSVC = 3, + CONSOLE_ATTACHED_ERROR = -1, +} consoleAttached = CONSOLE_UNATTACHED; /* Handle to stderr output of console. */ static HANDLE stderrHandle = NULL; @@ -530,58 +535,68 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority LPTSTR tstr; SDL_bool isstack; -#if !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) +#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) BOOL attachResult; DWORD attachError; - DWORD charsWritten; DWORD consoleMode; +#if !defined(HAVE_STDIO_H) + DWORD charsWritten; +#endif /* Maybe attach console and get stderr handle */ - if (consoleAttached == 0) { + if (consoleAttached == CONSOLE_UNATTACHED) { attachResult = AttachConsole(ATTACH_PARENT_PROCESS); if (!attachResult) { attachError = GetLastError(); if (attachError == ERROR_INVALID_HANDLE) { /* This is expected when running from Visual Studio */ /*OutputDebugString(TEXT("Parent process has no console\r\n"));*/ - consoleAttached = -1; + consoleAttached = CONSOLE_ATTACHED_MSVC; } else if (attachError == ERROR_GEN_FAILURE) { OutputDebugString(TEXT("Could not attach to console of parent process\r\n")); - consoleAttached = -1; + consoleAttached = CONSOLE_ATTACHED_ERROR; } else if (attachError == ERROR_ACCESS_DENIED) { /* Already attached */ - consoleAttached = 1; + consoleAttached = CONSOLE_ATTACHED_CONSOLE; } else { OutputDebugString(TEXT("Error attaching console\r\n")); - consoleAttached = -1; + consoleAttached = CONSOLE_ATTACHED_ERROR; } } else { /* Newly attached */ - consoleAttached = 1; + consoleAttached = CONSOLE_ATTACHED_CONSOLE; } - if (consoleAttached == 1) { + if (consoleAttached == CONSOLE_ATTACHED_CONSOLE) { stderrHandle = GetStdHandle(STD_ERROR_HANDLE); if (GetConsoleMode(stderrHandle, &consoleMode) == 0) { /* WriteConsole fails if the output is redirected to a file. Must use WriteFile instead. */ - consoleAttached = 2; + consoleAttached = CONSOLE_ATTACHED_FILE; } } } #endif /* !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) */ - length = SDL_strlen(SDL_GetLogPriorityPrefix(priority)) + SDL_strlen(message) + 1 + 1 + 1; output = SDL_small_alloc(char, length, &isstack); (void)SDL_snprintf(output, length, "%s%s\r\n", SDL_GetLogPriorityPrefix(priority), message); tstr = WIN_UTF8ToString(output); + +#if defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) + /* When running in MSVC and using stdio, rely on forwarding of stderr to the debug stream */ + if (consoleAttached != CONSOLE_ATTACHED_MSVC) { + /* Output to debugger */ + OutputDebugString(tstr); + } +#else /* Output to debugger */ OutputDebugString(tstr); +#endif #if !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) /* Screen output to stderr, if console was attached. */ - if (consoleAttached == 1) { + if (consoleAttached == CONSOLE_ATTACHED_CONSOLE) { if (!WriteConsole(stderrHandle, tstr, (DWORD)SDL_tcslen(tstr), &charsWritten, NULL)) { OutputDebugString(TEXT("Error calling WriteConsole\r\n")); if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) { @@ -589,7 +604,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority } } - } else if (consoleAttached == 2) { + } else if (consoleAttached == CONSOLE_ATTACHED_FILE) { if (!WriteFile(stderrHandle, output, (DWORD)SDL_strlen(output), &charsWritten, NULL)) { OutputDebugString(TEXT("Error calling WriteFile\r\n")); }