[PATCH] OS/ACPI: Make socket to acpid is non-blocking

Egbert Eich eich at freedesktop.org
Wed Aug 14 09:19:57 PDT 2013


If a connect to the acpid socket is delayed connect will
hang stalling the Xserver.  To avoid this this create a
non-blocking socket.
If connect returns EINPROGRESS use select() and getsockopt()
to check for completion of the connect request.
Use a different timeout to select() wether we connect for
the first time or reconnect.

Signed-off-by: Egbert Eich <eich at freedesktop.org>
---
 hw/xfree86/os-support/linux/lnx_acpi.c | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/hw/xfree86/os-support/linux/lnx_acpi.c b/hw/xfree86/os-support/linux/lnx_acpi.c
index 52cc708..364c12b 100644
--- a/hw/xfree86/os-support/linux/lnx_acpi.c
+++ b/hw/xfree86/os-support/linux/lnx_acpi.c
@@ -32,7 +32,7 @@
 #define ACPI_VIDEO_HEAD_INVALID		(~0u - 1)
 #define ACPI_VIDEO_HEAD_END		(~0u)
 
-static PMClose doLnxACPIOpen(void);
+static PMClose doLnxACPIOpen(struct timeval *);
 static void lnxCloseACPI(void);
 static pointer ACPIihPtr = NULL;
 static OsTimerPtr acpiTimer = NULL;
@@ -58,8 +58,9 @@ lnxACPIReopen(OsTimerPtr timer, CARD32 time, pointer arg)
 static CARD32
 lnxACPICheckTimer(OsTimerPtr timer, CARD32 now, pointer arg)
 {
+    struct timeval timeval = { 0, 0 };
     DebugF("ACPI: trying to reopen\n");
-    if (doLnxACPIOpen()) {
+    if (doLnxACPIOpen(&timeval)) {
         DebugF("ACPI: successfully reopened\n");
         acpiTimer = NULL;
         return 0;
@@ -146,7 +147,7 @@ lnxACPIConfirmEventToOs(int fd, pmEvent event)
 }
 
 static PMClose
-doLnxACPIOpen(void)
+doLnxACPIOpen(struct timeval *tv_p)
 {
     int fd = -1;
     struct sockaddr_un addr;
@@ -157,13 +158,34 @@ doLnxACPIOpen(void)
         return NULL;
 
     DebugF("ACPI: Opening device\n");
-    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
     if (fd > -1) {
         memset(&addr, 0, sizeof(addr));
         addr.sun_family = AF_UNIX;
         strcpy(addr.sun_path, ACPI_SOCKET);
         r = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
         if (r == -1) {
+            int sock_errno = errno;
+            if (sock_errno == EINPROGRESS) {
+                fd_set fds;
+                int result;
+                do {
+                    FD_ZERO(&fds);
+                    FD_SET(fd, &fds);
+                    result = select(fd + 1, NULL, &fds, NULL, tv_p);
+                }  while (result < 0 && errno == EINTR);
+                if (result < 0)
+                    sock_errno = errno;
+                else if (result > 0) {
+                    int sock_errno;
+                    socklen_t size = sizeof(sock_errno);
+                    if (0 > getsockopt(fd, SOL_SOCKET, SO_ERROR, &sock_errno,
+                                       &size))
+                        sock_errno = errno;
+                    if (!sock_errno)
+                        goto success;
+                }
+            }
             if (errno != warned)
                 xf86MsgVerb(X_WARNING,3,"Open ACPI failed (%s) (%s)\n",
                             ACPI_SOCKET, strerror(errno));
@@ -175,6 +197,7 @@ doLnxACPIOpen(void)
     } else
         return NULL;
 
+ success:
     xf86PMGetEventFromOs = lnxACPIGetEventFromOs;
     xf86PMConfirmEventToOs = lnxACPIConfirmEventToOs;
     ACPIihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL);
@@ -195,8 +218,9 @@ PMClose
 lnxACPIOpen(void)
 {
     PMClose ret;
+    struct timeval timeval = { 0, 30000 };
     DebugF("ACPI: OSPMOpen called\n");
-    ret = doLnxACPIOpen();
+    ret = doLnxACPIOpen(&timeval);
 
     return ret;
 }
-- 
1.8.1.4



More information about the xorg-devel mailing list