Hello *,

Could something like the attached fix be merged? It fixes a problem where the 
kernel requests the X server to relinquish its terminal via SIGUSR1, but the X 
server blocks in select() nevertheless.

The problem is not easily triggered, it requires a relatively idle system (no 
user 
input, drawing), where "something" issues chvt just before the server blocks 
waiting for events.

Best regards
Helge
-- 
Dr.-Ing. Helge Bahmann
Berater, Geschäftsbereich Hochsicherheit
secunet Security Networks AG

Tel.: +49 201 5454-1231, Fax: +49 201 5454-1239, Mobil: +49 160 97215135
E-Mail: [email protected] 
Kronprinzenstraße 30, 45128 Essen, Deutschland
www.secunet.com <http://www.secunet.com/>  

________________________________________________________________________________________

Sitz: Kronprinzenstraße 30, 45128 Essen, Deutschland / Amtsgericht Essen HRB 
13615
Vorstand: Dr. Rainer Baumgart (Vors.), Thomas Pleines / 
Aufsichtsratsvorsitzender: 
Dr. Karsten Ottenberg
_______________________________________________________________________________________

From 60630d080769636dcae67189c75d223ef4654b1d Mon Sep 17 00:00:00 2001
From: Helge Bahmann <[email protected]>
Date: Mon, 7 May 2012 13:25:04 +0200
Subject: [PATCH] Close vtRequestsPending race

Add pipe to forcibly wake up main event handling loop from within SIGUSR1
handler. This closes a race between the signal handler asserting
vtRequestsPending as well as the main thread checking it and blocking in the
main event loop.
---
 hw/xfree86/common/xf86Events.c          |   15 ++++++++++++++-
 hw/xfree86/common/xf86Globals.c         |    2 ++
 hw/xfree86/common/xf86Init.c            |    2 +-
 hw/xfree86/common/xf86Priv.h            |    1 +
 hw/xfree86/common/xf86Privstr.h         |    2 ++
 hw/xfree86/os-support/linux/lnx_init.c  |    8 ++++++++
 hw/xfree86/os-support/shared/VTsw_usl.c |    4 ++++
 7 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 84c0d18..4313444 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -233,6 +233,13 @@ xf86ProcessActionEvent(ActionEvent action, void *arg)
     }
 }
 
+void xf86Block(pointer data, OSTimePtr timeout, pointer pReadMask)
+{
+    fd_set *SelectMask = (fd_set*)pReadMask;
+    if (xf86Info.vtRequestReadFD != -1)
+	FD_SET(xf86Info.vtRequestReadFD, SelectMask);
+}
+
 /*
  * xf86Wakeup --
  *      Os wakeup handler.
@@ -242,12 +249,18 @@ xf86ProcessActionEvent(ActionEvent action, void *arg)
 void
 xf86Wakeup(pointer blockData, int err, pointer pReadmask)
 {
-    fd_set* LastSelectMask = (fd_set*)pReadmask;
+    fd_set *LastSelectMask = (fd_set*)pReadmask;
     fd_set devicesWithInput;
     InputInfoPtr pInfo;
 
     if (err >= 0) {
 
+	if (xf86Info.vtRequestReadFD != -1 &&
+	    FD_ISSET(xf86Info.vtRequestReadFD, LastSelectMask)) {
+	    char c;
+	    read(xf86Info.vtRequestReadFD, &c, 1);
+	}
+
 	XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
 	if (XFD_ANYSET(&devicesWithInput)) {
 	    pInfo = xf86InputDevs;
diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c
index 16d5557..03d24d5 100644
--- a/hw/xfree86/common/xf86Globals.c
+++ b/hw/xfree86/common/xf86Globals.c
@@ -99,6 +99,8 @@ xf86InfoRec xf86Info = {
     .vtSysreq                   = FALSE,
     .lastEventTime              = -1,
     .vtRequestsPending          = FALSE,
+    .vtRequestReadFD            = -1,
+    .vtRequestWriteFD           = -1,
 #ifdef sun
     .vtPendingNum               = -1,
 #endif
diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c
index 0b36163..e271024 100644
--- a/hw/xfree86/common/xf86Init.c
+++ b/hw/xfree86/common/xf86Init.c
@@ -787,7 +787,7 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv)
   xf86Resetting = FALSE;
   xf86Initialising = FALSE;
 
-  RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, xf86Wakeup,
+  RegisterBlockAndWakeupHandlers(xf86Block, xf86Wakeup,
 				 NULL);
 }
 
diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h
index 7137a53..aab18af 100644
--- a/hw/xfree86/common/xf86Priv.h
+++ b/hw/xfree86/common/xf86Priv.h
@@ -132,6 +132,7 @@ extern _X_EXPORT void DoShowOptions(void);
 
 /* xf86Events.c */
 
+extern _X_EXPORT void xf86Block(pointer blockData, OSTimePtr timeout, pointer pReadmask);
 extern _X_EXPORT void xf86Wakeup(pointer blockData, int err, pointer pReadmask);
 extern _X_HIDDEN int xf86SigWrapper(int signo);
 extern _X_EXPORT void xf86HandlePMEvents(int fd, pointer data);
diff --git a/hw/xfree86/common/xf86Privstr.h b/hw/xfree86/common/xf86Privstr.h
index 608f9bd..da79974 100644
--- a/hw/xfree86/common/xf86Privstr.h
+++ b/hw/xfree86/common/xf86Privstr.h
@@ -62,6 +62,8 @@ typedef struct {
     /* event handler part */
     int			lastEventTime;
     Bool		vtRequestsPending;
+    int			vtRequestReadFD;
+    int			vtRequestWriteFD;
 #ifdef sun
     int			vtPendingNum;
 #endif
diff --git a/hw/xfree86/os-support/linux/lnx_init.c b/hw/xfree86/os-support/linux/lnx_init.c
index 9c71a42..e8f3ca3 100644
--- a/hw/xfree86/os-support/linux/lnx_init.c
+++ b/hw/xfree86/os-support/linux/lnx_init.c
@@ -180,6 +180,7 @@ xf86OpenConsole(void)
         if (!ShareVTs)
         {
             struct termios nTty;
+            int pipefds[2];
 
 	    /*
 	     * now get the VT.  This _must_ succeed, or else fail completely.
@@ -190,6 +191,13 @@ xf86OpenConsole(void)
 	        FatalError("xf86OpenConsole: VT_GETMODE failed %s\n",
 		           strerror(errno));
 
+	    if (pipe(pipefds) < 0)
+	        FatalError("xf86OpenConsole: pipe failed: %s\n",
+		    strerror(errno));
+	    fcntl(pipefds[0], F_SETFL, O_NONBLOCK);
+	    fcntl(pipefds[1], F_SETFL, O_NONBLOCK);
+	    xf86Info.vtRequestReadFD = pipefds[0];
+	    xf86Info.vtRequestWriteFD = pipefds[1];
 	    signal(SIGUSR1, xf86VTRequest);
 
 	    VT.mode = VT_PROCESS;
diff --git a/hw/xfree86/os-support/shared/VTsw_usl.c b/hw/xfree86/os-support/shared/VTsw_usl.c
index 818de17..9374361 100644
--- a/hw/xfree86/os-support/shared/VTsw_usl.c
+++ b/hw/xfree86/os-support/shared/VTsw_usl.c
@@ -43,8 +43,12 @@
 void
 xf86VTRequest(int sig)
 {
+	char c = 0;
+	
 	signal(sig, (void(*)(int))xf86VTRequest);
 	xf86Info.vtRequestsPending = TRUE;
+	if (xf86Info.vtRequestWriteFD != -1)
+		write(xf86Info.vtRequestWriteFD, &c, 1);
 	return;
 }
 
-- 
1.7.2.5

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to