From f5f04a10f5d14abc7a0ab90ef42c88fb45e410cb Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 15 Dec 2020 14:40:09 +0100 Subject: [PATCH] Add a project setting to enable stdout flushing in release builds This can be used in server builds for journalctl compatibility. (cherry picked from commit 341b9cf15a6df3dae1ba6218b8545feec41fa728) --- core/io/logger.cpp | 20 +++++++++++--------- doc/classes/ProjectSettings.xml | 8 ++++++++ main/main.cpp | 5 +++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/core/io/logger.cpp b/core/io/logger.cpp index 57d7f8cd177..4796d27bad2 100644 --- a/core/io/logger.cpp +++ b/core/io/logger.cpp @@ -33,6 +33,7 @@ #include "core/os/dir_access.h" #include "core/os/os.h" #include "core/print_string.h" +#include "core/project_settings.h" // va_copy was defined in the C99, but not in C++ standards before C++11. // When you compile C++ without --std=c++ option, compilers still define @@ -204,15 +205,14 @@ void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) { } va_end(list_copy); file->store_buffer((uint8_t *)buf, len); + if (len >= static_buf_size) { Memory::free_static(buf); } -#ifdef DEBUG_ENABLED - const bool need_flush = true; -#else - bool need_flush = p_err; -#endif - if (need_flush) { + + if (p_err || GLOBAL_GET("application/run/flush_stdout_on_print")) { + // Don't always flush when printing stdout to avoid performance + // issues when `print()` is spammed in release builds. file->flush(); } } @@ -231,9 +231,11 @@ void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) { vfprintf(stderr, p_format, p_list); } else { vprintf(p_format, p_list); -#ifdef DEBUG_ENABLED - fflush(stdout); -#endif + if (GLOBAL_GET("application/run/flush_stdout_on_print")) { + // Don't always flush when printing stdout to avoid performance + // issues when `print()` is spammed in release builds. + fflush(stdout); + } } } diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index e0ddedd948f..de280ff25ef 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -248,6 +248,14 @@ If [code]true[/code], disables printing to standard output in an exported build. + + If [code]true[/code], flushes the standard output stream every time a line is printed. This affects both terminal logging and file logging. + When running a project, this setting must be enabled if you want logs to be collected by service managers such as systemd/journalctl. This setting is disabled by default on release builds, since flushing on every printed line will negatively affect performance if lots of lines are printed in a rapid succession. Also, if this setting is enabled, logged files will still be written successfully if the application crashes or is otherwise killed by the user (without being closed "normally"). + [b]Note:[/b] Regardless of this setting, the standard error stream ([code]stderr[/code]) is always flushed when a line is printed to it. + + + Debug build override for [member application/run/flush_stdout_on_print], as performance is less important during debugging. + Forces a delay between frames in the main loop (in milliseconds). This may be useful if you plan to disable vertical synchronization. diff --git a/main/main.cpp b/main/main.cpp index 81bc9a58f0c..866184336ca 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -971,6 +971,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } #endif + // Only flush stdout in debug builds by default, as spamming `print()` will + // decrease performance if this is enabled. + GLOBAL_DEF("application/run/flush_stdout_on_print", false); + GLOBAL_DEF("application/run/flush_stdout_on_print.debug", true); + GLOBAL_DEF("logging/file_logging/enable_file_logging", false); // Only file logging by default on desktop platforms as logs can't be // accessed easily on mobile/Web platforms (if at all).