From 00c854e3cfb6ef5f18905ea9d5d48c40dc34b603 Mon Sep 17 00:00:00 2001 From: Joel Rosdahl Date: Sun, 10 Nov 2024 21:38:54 +0100 Subject: [PATCH] fix: Synchonize writing to the log file Fixes #350. --- src/ccache/ccache.cpp | 37 ++++++++++++++++--------------- src/ccache/util/logging.cpp | 43 +++++++++++++++++++++++-------------- src/ccache/util/logging.hpp | 26 +++++++++++++--------- 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/src/ccache/ccache.cpp b/src/ccache/ccache.cpp index efc833ed..7530c768 100644 --- a/src/ccache/ccache.cpp +++ b/src/ccache/ccache.cpp @@ -2366,29 +2366,32 @@ find_compiler(Context& ctx, static void initialize(Context& ctx, const char* const* argv, bool masquerading_as_compiler) { - LOG("=== CCACHE {} STARTED =========================================", - CCACHE_VERSION); - - LOG("Configuration file: {}", ctx.config.config_path()); - LOG("System configuration file: {}", ctx.config.system_config_path()); - - if (!ctx.config.log_file().empty() || ctx.config.debug()) { - ctx.config.visit_items([&ctx](const std::string& key, - const std::string& value, - const std::string& origin) { + if (util::logging::enabled()) { + util::logging::BulkLogger logger; + + BULK_LOG(logger, + "=== CCACHE {} STARTED =========================================", + CCACHE_VERSION); + BULK_LOG(logger, "Configuration file: {}", ctx.config.config_path()); + BULK_LOG( + logger, "System configuration file: {}", ctx.config.system_config_path()); + + ctx.config.visit_items([&](const std::string& key, + const std::string& value, + const std::string& origin) { const auto& log_value = key == "remote_storage" ? ctx.storage.get_remote_storage_config_for_logging() : value; - BULK_LOG("Config: ({}) {} = {}", origin, key, log_value); + BULK_LOG(logger, "Config: ({}) {} = {}", origin, key, log_value); }); - } - LOG("Command line: {}", util::format_argv_for_logging(argv)); - LOG("Hostname: {}", util::get_hostname()); - LOG("Working directory: {}", ctx.actual_cwd); - if (ctx.apparent_cwd != ctx.actual_cwd) { - LOG("Apparent working directory: {}", ctx.apparent_cwd); + BULK_LOG(logger, "Command line: {}", util::format_argv_for_logging(argv)); + BULK_LOG(logger, "Hostname: {}", util::get_hostname()); + BULK_LOG(logger, "Working directory: {}", ctx.actual_cwd); + if (ctx.apparent_cwd != ctx.actual_cwd) { + BULK_LOG(logger, "Apparent working directory: {}", ctx.apparent_cwd); + } } ctx.storage.initialize(); diff --git a/src/ccache/util/logging.cpp b/src/ccache/util/logging.cpp index 178dbd06..0e90dff8 100644 --- a/src/ccache/util/logging.cpp +++ b/src/ccache/util/logging.cpp @@ -78,7 +78,7 @@ do_log(std::string_view message, bool bulk) { static char prefix[200]; - if (!bulk) { + if (!bulk || prefix[0] == '\0') { char timestamp[100]; auto now = util::TimePoint::now(); auto tm = util::localtime(now); @@ -98,12 +98,16 @@ do_log(std::string_view message, bool bulk) static_cast(getpid())); } - if (logfile - && (fputs(prefix, *logfile) == EOF - || fwrite(message.data(), message.length(), 1, *logfile) != 1 - || fputc('\n', *logfile) == EOF - || (!bulk && fflush(*logfile) == EOF))) { - print_fatal_error_and_exit(); + if (logfile) { + util::FileLock lock(fileno(*logfile)); + if (!bulk) { + std::ignore = lock.acquire(); // Garbled logs are better than no logs + } + if (fputs(prefix, *logfile) == EOF + || fwrite(message.data(), message.length(), 1, *logfile) != 1 + || fputc('\n', *logfile) == EOF || fflush(*logfile) == EOF) { + print_fatal_error_and_exit(); + } } #ifdef HAVE_SYSLOG if (use_syslog) { @@ -164,15 +168,6 @@ log(std::string_view message) do_log(message, false); } -void -bulk_log(std::string_view message) -{ - if (!enabled()) { - return; - } - do_log(message, true); -} - void dump_log(const fs::path& path) { @@ -187,4 +182,20 @@ dump_log(const fs::path& path) } } +BulkLogger::BulkLogger() : m_file_lock(logfile ? fileno(*logfile) : -1) +{ + if (logfile) { + std::ignore = m_file_lock.acquire(); // Garbled logs are better than no logs + } +} + +void +BulkLogger::log(std::string_view message) +{ + if (!enabled()) { + return; + } + do_log(message, true); +} + } // namespace util::logging diff --git a/src/ccache/util/logging.hpp b/src/ccache/util/logging.hpp index 1628759d..92c4186e 100644 --- a/src/ccache/util/logging.hpp +++ b/src/ccache/util/logging.hpp @@ -18,6 +18,8 @@ #pragma once +#include + #include #include @@ -40,12 +42,8 @@ // Log a message (plus a newline character) described by a format string with at // least one placeholder without flushing and with a reused timestamp. `format` // is checked at compile time. -#define BULK_LOG(format_, ...) \ - do { \ - if (util::logging::enabled()) { \ - util::logging::bulk_log(fmt::format(FMT_STRING(format_), __VA_ARGS__)); \ - } \ - } while (false) +#define BULK_LOG(logger_, format_, ...) \ + logger_.log(fmt::format(FMT_STRING(format_), __VA_ARGS__)); namespace util::logging { @@ -59,11 +57,19 @@ bool enabled(); // Log `message` (plus a newline character). void log(std::string_view message); -// Log `message` (plus a newline character) without flushing and with a reused -// timestamp. -void bulk_log(std::string_view message); - // Write the current log memory buffer to `path`. void dump_log(const std::filesystem::path& path); +class BulkLogger +{ +public: + BulkLogger(); + + // Log `message` (plus a newline character) with a reused timestamp. + void log(std::string_view message); + +private: + util::FileLock m_file_lock; +}; + } // namespace util::logging -- 2.47.2