[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