[PATCH:xserver] Use unique logfile names when starting server with -displayfd

Alan Coopersmith alan.coopersmith at oracle.com
Fri Jan 1 18:11:14 PST 2016


Fixes https://bugs.freedesktop.org/show_bug.cgi?id=93212

Previously all X servers started with -displayfd would overwrite
Xorg.0.log - now a temporary name of Xorg.pid-<pid>.log is used
until after -displayfd finds an open display - then it is renamed
to the traditional Xorg.<display>.log name.

Signed-off-by: Alan Coopersmith <alan.coopersmith at oracle.com>
---
 include/os.h    |   2 +
 os/connection.c |   1 +
 os/log.c        | 126 +++++++++++++++++++++++++++++++++++++++++++-------------
 3 files changed, 101 insertions(+), 28 deletions(-)

diff --git a/include/os.h b/include/os.h
index e7c1936..461d5d6 100644
--- a/include/os.h
+++ b/include/os.h
@@ -626,6 +626,8 @@ typedef enum {
 
 extern _X_EXPORT const char *
 LogInit(const char *fname, const char *backup);
+extern void
+LogSetDisplay(void);
 extern _X_EXPORT void
 LogClose(enum ExitCode error);
 extern _X_EXPORT Bool
diff --git a/os/connection.c b/os/connection.c
index 492d79f..2a4fc8d 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -431,6 +431,7 @@ CreateWellKnownSockets(void)
             FatalError("Failed to find a socket to listen on");
         snprintf(dynamic_display, sizeof(dynamic_display), "%d", i);
         display = dynamic_display;
+        LogSetDisplay();
     }
 
     ListenTransFds = xallocarray(ListenTransCount, sizeof (int));
diff --git a/os/log.c b/os/log.c
index 3db5c53..6168d59 100644
--- a/os/log.c
+++ b/os/log.c
@@ -85,6 +85,7 @@ OR PERFORMANCE OF THIS SOFTWARE.
 #include <sys/stat.h>
 #include <stdarg.h>
 #include <stdlib.h>             /* for malloc() */
+#include <errno.h>
 
 #include "input.h"
 #include "site.h"
@@ -181,16 +182,64 @@ strlen_sigsafe(const char *s)
 }
 
 /*
+ * LogFilePrep is called to setup files for logging, including getting
+ * an old file out of the way, but it doesn't actually open the file,
+ * since it may be used for renaming a file we're already logging to.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static char *
+LogFilePrep(const char *fname, const char *backup, const char *idstring)
+{
+    char *logFileName = NULL;
+
+    if (asprintf(&logFileName, fname, idstring) == -1)
+        FatalError("Cannot allocate space for the log file name\n");
+
+    if (backup && *backup) {
+        struct stat buf;
+
+        if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
+            char *suffix;
+            char *oldLog;
+
+            if ((asprintf(&suffix, backup, idstring) == -1) ||
+                (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) {
+                FatalError("Cannot allocate space for the log file name\n");
+            }
+            free(suffix);
+
+            if (rename(logFileName, oldLog) == -1) {
+                FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
+                           logFileName, oldLog);
+            }
+            free(oldLog);
+        }
+    }
+    else {
+        if (remove(logFileName) != 0) {
+            FatalError("Cannot remove old log file \"%s\": %s\n",
+                       logFileName, strerror(errno));
+        }
+    }
+
+    return logFileName;
+}
+#pragma GCC diagnostic pop
+
+/*
  * LogInit is called to start logging to a file.  It is also called (with
  * NULL arguments) when logging to a file is not wanted.  It must always be
  * called, otherwise log messages will continue to accumulate in a buffer.
  *
  * %s, if present in the fname or backup strings, is expanded to the display
- * string.
+ * string (or to a string containing the pid if the display is not yet set).
  */
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+static char *saved_log_fname;
+static char *saved_log_backup;
+static char *saved_log_tempname;
 
 const char *
 LogInit(const char *fname, const char *backup)
@@ -198,30 +247,22 @@ LogInit(const char *fname, const char *backup)
     char *logFileName = NULL;
 
     if (fname && *fname) {
-        if (asprintf(&logFileName, fname, display) == -1)
-            FatalError("Cannot allocate space for the log file name\n");
-
-        if (backup && *backup) {
-            struct stat buf;
-
-            if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) {
-                char *suffix;
-                char *oldLog;
-
-                if ((asprintf(&suffix, backup, display) == -1) ||
-                    (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1))
-                    FatalError("Cannot allocate space for the log file name\n");
-                free(suffix);
-                if (rename(logFileName, oldLog) == -1) {
-                    FatalError("Cannot move old log file \"%s\" to \"%s\"\n",
-                               logFileName, oldLog);
-                }
-                free(oldLog);
-            }
-        }
-        else {
-            unlink(logFileName);
-        }
+        if (displayfd != -1) {
+            /* Display isn't set yet, so we can't use it in filenames yet. */
+            char pidstring[32];
+            snprintf(pidstring, sizeof(pidstring), "pid-%ld",
+                     (unsigned long) getpid());
+            logFileName = LogFilePrep(fname, backup, pidstring);
+            saved_log_tempname = logFileName;
+
+            /* Save the patterns for use when the display is named. */
+            saved_log_fname = strdup(fname);
+            if (backup == NULL)
+                saved_log_backup = NULL;
+            else
+                saved_log_backup = strdup(backup);
+        } else
+            logFileName = LogFilePrep(fname, backup, display);
         if ((logFile = fopen(logFileName, "w")) == NULL)
             FatalError("Cannot open log file \"%s\"\n", logFileName);
         setvbuf(logFile, NULL, _IONBF, 0);
@@ -251,7 +292,36 @@ LogInit(const char *fname, const char *backup)
 
     return logFileName;
 }
-#pragma GCC diagnostic pop
+
+void
+LogSetDisplay(void)
+{
+    if (saved_log_fname) {
+        char *logFileName;
+
+        logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display);
+
+        if (rename(saved_log_tempname, logFileName) == 0) {
+            LogMessageVerb(X_PROBED, 0,
+                           "Log file renamed from \"%s\" to \"%s\"\n",
+                           saved_log_tempname, logFileName);
+
+            if (strlen(saved_log_tempname) >= strlen(logFileName))
+                strncpy(saved_log_tempname, logFileName,
+                        strlen(saved_log_tempname));
+        }
+        else {
+            ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n",
+                   saved_log_tempname, logFileName, strerror(errno));
+        }
+
+        /* free newly allocated string - can't free old one since existing
+           pointers to it may exist in DDX callers. */
+        free(logFileName);
+        free(saved_log_fname);
+        free(saved_log_backup);
+    }
+}
 
 void
 LogClose(enum ExitCode error)
-- 
2.6.1



More information about the xorg-devel mailing list