From: Branden Robinson <branden@debian.org>
Date: Wed, 20 Aug 2008 02:56:41 +0200
Subject: add support for logfile rotation

- Implement new ReopenLogFile() and ReopenLogFileNotify() functions.
  ReopenLogFileNotify() is a signal handler for SIGUSR2.
- Move the definition of the WRITES() macro from error.c to dm_error.h
  so that dm.c can use it as well.
- Document xdm's signal handling in its manpage.

Forward-ported by Eugene Konev and Julien Cristau.

Last-Updated: 2025-12-08
---
 include/dm_error.h |  2 ++
 man/xdm.man        | 31 +++++++++++++++++++++++++++++++
 xdm/dm.c           | 40 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/xdm/dm.c b/xdm/dm.c
index 73280b2..864c5aa 100644
--- a/xdm/dm.c
+++ b/xdm/dm.c
@@ -83,8 +83,10 @@ from The Open Group.
 # endif
 #endif
 
-static void	StopAll (int n), RescanNotify (int n);
+static void	StopAll (int n), RescanNotify (int n),
+				ReopenLogFileNotify (int n);
 static void	RescanServers (void);
+static void	ReopenLogFile (void);
 static void	RestartDisplay (struct display *d, int forceReserver);
 static void	ScanServers (void);
 static void	SetAccessFileTime (void);
@@ -93,6 +95,7 @@ static void	StartDisplays (void);
 static void	TerminateProcess (pid_t pid, int signal);
 
 volatile int	Rescan;
+volatile int	Reopen;
 static long	ServersModTime, ConfigModTime, AccessFileModTime;
 
 int nofork_session = 0;
@@ -242,6 +245,7 @@ main (int argc, char **argv)
     AddOtherEntropy();
 #endif
     (void) Signal (SIGHUP, RescanNotify);
+    (void) Signal (SIGUSR2, ReopenLogFileNotify);
     (void) Signal (SIGCHLD, ChildNotify);
     Debug ("startup successful; entering main loop\n");
     while (
@@ -250,6 +254,11 @@ main (int argc, char **argv)
 #endif
 	   AnyDisplaysLeft ())
     {
+	if (Reopen)
+	{
+	    ReopenLogFile ();
+		Reopen = 0;
+	}
 	if (Rescan)
 	{
 	    RescanServers ();
@@ -274,10 +283,31 @@ RescanNotify (int n)
     int olderrno = errno;
 
     Debug ("Caught SIGHUP\n");
+    Reopen = 1;
     Rescan = 1;
     errno = olderrno;
 }
 
+/*
+ * Handle a SIGUSR2: set variable that will instruct the main loop to
+ * reopen the log file.
+ */
+static void
+ReopenLogFileNotify (int n)
+{
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+    int olderrno = errno;
+#endif
+
+    /* Debug() is not safe inside a signal handler. */
+    WRITES(STDERR_FILENO, "ReopenLogFileNotify handling SIGUSR2\n");
+    Reopen = 1;
+#ifdef SIGNALS_RESET_WHEN_CAUGHT
+    (void) Signal (SIGUSR2, ReopenLogFileNotify);
+    errno = olderrno;
+#endif
+}
+
 static void
 ScanServers (void)
 {
@@ -345,6 +375,14 @@ RescanServers (void)
     StartDisplays ();
 }
 
+static void
+ReopenLogFile (void)
+{
+    Debug ("closing standard error file descriptor %d\n", STDERR_FILENO);
+    close (STDERR_FILENO);
+    InitErrorLog ();
+}
+
 static void
 SetConfigFileTime (void)
 {
diff --git a/include/dm_error.h b/include/dm_error.h
index 09c124e..da94cc7 100644
--- a/include/dm_error.h
+++ b/include/dm_error.h
@@ -34,6 +34,8 @@ authorization.
 #ifndef _DM_ERROR_H_
 # define _DM_ERROR_H_ 1
 
+#define WRITES(fd, buf) write(fd, buf, strlen(buf))
+
 extern void Debug        (const char * fmt, ...) _X_ATTRIBUTE_PRINTF(1,2);
 extern void InitErrorLog (void);
 extern void LogAppend    (const char * fmt, ...) _X_ATTRIBUTE_PRINTF(1,2);
diff --git a/man/xdm.man b/man/xdm.man
index 5e63e48..734942a 100644
--- a/man/xdm.man
+++ b/man/xdm.man
@@ -1420,6 +1420,37 @@ isn't very good at doing is coexisting with other window systems.  To use
 multiple window systems on the same hardware, you'll probably be more
 interested in
 .I xinit.
+.SH "ASYNCHRONOUS EVENTS"
+.B xdm
+uses
+.B SIGALRM
+and
+.B SIGUSR1
+for its own inter-process communication purposes, managing the relationship
+between the parent
+.B xdm
+process and its children.
+Sending these signals to any
+.B xdm
+process may result in unexpected behavior.
+.TP
+.B SIGHUP
+causes
+.B xdm
+to rescan its configuration files and reopen its log file.
+.TP
+.B SIGTERM
+causes
+.B xdm
+to terminate its children and shut down.
+.TP
+.B SIGUSR2
+causes
+.B xdm
+to reopen its log file.
+This is useful if log rotation is desired, but
+.B SIGHUP
+is too disruptive.
 .SH FILES
 .TP 20
 .I XDMDIR/xdm-config
