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
