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 <e...@freedesktop.org> --- v3: Increase select() timeout when retrying as suggested by Keith Packard <kei...@keithp.com>. Fix some errno confusion. hw/xfree86/os-support/linux/lnx_acpi.c | 39 +++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/hw/xfree86/os-support/linux/lnx_acpi.c b/hw/xfree86/os-support/linux/lnx_acpi.c index 52cc708..9cbd840 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, 30000 }; 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,17 +158,37 @@ 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) { - if (errno != warned) + 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) { + 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 (sock_errno != warned) xf86MsgVerb(X_WARNING,3,"Open ACPI failed (%s) (%s)\n", - ACPI_SOCKET, strerror(errno)); - warned = errno; + ACPI_SOCKET, strerror(sock_errno)); + warned = sock_errno; shutdown(fd, SHUT_RDWR); close(fd); return NULL; @@ -175,6 +196,7 @@ doLnxACPIOpen(void) } else return NULL; + success: xf86PMGetEventFromOs = lnxACPIGetEventFromOs; xf86PMConfirmEventToOs = lnxACPIConfirmEventToOs; ACPIihPtr = xf86AddGeneralHandler(fd, xf86HandlePMEvents, NULL); @@ -195,8 +217,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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel