]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
logging: try to reopen message log on cyclelogs command
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 20 Mar 2025 11:57:37 +0000 (12:57 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 20 Mar 2025 15:34:35 +0000 (16:34 +0100)
When the cyclelogs command is issued, check if the file specified by the
-l option is still in its place and if not try opening it again. If that
fails (e.g. due to chrony no longer having root privileges), keep the
old file handle to avoid losing log messages.

doc/chronyc.adoc
logging.c

index b3692f43ba6b94087cd8e2c1f1c1cad4d9990283..5780e28186c4b0784131caee1ff6a2f98b87beb1 100644 (file)
@@ -1467,6 +1467,13 @@ purged. An example of how to do this is shown below.
 # chronyc cyclelogs
 # rm /var/log/chrony/measurements1.log
 ----
++
+Note that log files enabled by the *log* directive are opened when the first
+entry is made. The message log file specified by the *chronyd*'s *-l* option is
+opened early on start and closed on the *cyclelogs* command only if opening of
+the new file succeeds to avoid losing messages. If *chronyd* is configured to
+drop root privileges and the directory containg the log file is not writable
+for the specified user, *chronyd* will not be able to open the file again.
 
 [[dump]]*dump*::
 The *dump* command causes *chronyd* to write its current history of
index 732165e9d96f8cd9f1be981cd27e7233b455ae7c..db2e6f604cead4a9ddf6bedccbbd1f373dab50ef 100644 (file)
--- a/logging.c
+++ b/logging.c
@@ -46,6 +46,7 @@ static LOG_Context log_contexts;
 /* Flag indicating we have initialised */
 static int initialised = 0;
 
+static char *file_log_path = NULL;
 static FILE *file_log = NULL;
 static int system_log = 0;
 
@@ -92,6 +93,9 @@ LOG_Finalise(void)
 
   if (file_log)
     fclose(file_log);
+  file_log = NULL;
+  Free(file_log_path);
+  file_log_path = NULL;
 
   LOG_CycleLogFiles();
 
@@ -200,27 +204,42 @@ void LOG_Message(LOG_Severity severity,
 
 /* ================================================== */
 
-void
-LOG_OpenFileLog(const char *log_file)
+static FILE *
+open_file_log(const char *log_file, char mode)
 {
   FILE *f;
 
   if (log_file) {
-    f = UTI_OpenFile(NULL, log_file, NULL, 'A', 0640);
+    f = UTI_OpenFile(NULL, log_file, NULL, mode, 0640);
   } else {
     f = stderr;
   }
 
   /* Enable line buffering */
-  setvbuf(f, NULL, _IOLBF, BUFSIZ);
+  if (f)
+    setvbuf(f, NULL, _IOLBF, BUFSIZ);
+
+  return f;
+}
+
+/* ================================================== */
+
+void
+LOG_OpenFileLog(const char *log_file)
+{
+  if (file_log_path)
+    Free(file_log_path);
+  if (log_file)
+    file_log_path = Strdup(log_file);
+  else
+    file_log_path = NULL;
 
   if (file_log && file_log != stderr)
     fclose(file_log);
 
-  file_log = f;
+  file_log = open_file_log(file_log_path, 'A');
 }
 
-
 /* ================================================== */
 
 void
@@ -385,14 +404,29 @@ LOG_FileWrite(LOG_FileID id, const char *format, ...)
 void
 LOG_CycleLogFiles(void)
 {
+  struct stat st;
   LOG_FileID i;
+  FILE *f;
 
+  /* The log will be opened later when an entry is logged */
   for (i = 0; i < n_filelogs; i++) {
     if (logfiles[i].file)
       fclose(logfiles[i].file);
     logfiles[i].file = NULL;
     logfiles[i].writes = 0;
   }
+
+  /* Try to open the log specified by the -l option, but only if nothing is
+     present at its path to avoid unnecessary error messages.  Keep the
+     original file if that fails (the process might no longer have the
+     necessary privileges to write in the directory). */
+  if (file_log && file_log != stderr && stat(file_log_path, &st) < 0 && errno == ENOENT) {
+    f = open_file_log(file_log_path, 'a');
+    if (f) {
+      fclose(file_log);
+      file_log = f;
+    }
+  }
 }
 
 /* ================================================== */