]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
fix: Synchonize writing to the log file
authorJoel Rosdahl <joel@rosdahl.net>
Sun, 10 Nov 2024 20:38:54 +0000 (21:38 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 16 Nov 2024 12:24:18 +0000 (13:24 +0100)
Fixes #350.

src/ccache/ccache.cpp
src/ccache/util/logging.cpp
src/ccache/util/logging.hpp

index efc833edd5b036fce48b8b82c4e0b35fabe36c2c..7530c76826abfaed9c4178f8bd463ab7ac1f8957 100644 (file)
@@ -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();
index 178dbd06eaad2ad246c968d795a933e4c90b2dc4..0e90dff8f0e6df311d173b46ef0d234e29ce72ae 100644 (file)
@@ -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<int>(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
index 1628759d26a480ec7e14fdfc6c11cdd2326afd53..92c4186e8ce6a2396dbdb0f806d8a34e0c0133e7 100644 (file)
@@ -18,6 +18,8 @@
 
 #pragma once
 
+#include <ccache/util/filelock.hpp>
+
 #include <fmt/core.h>
 #include <fmt/format.h>
 
 // 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