[PATCH v3] OS/ACPI: Make socket to acpid is non-blocking
Egbert Eich
eich at freedesktop.org
Fri Nov 15 05:14:03 PST 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>
---
v3: Increase select() timeout when retrying as suggested by
Keith Packard <keithp at 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
More information about the xorg-devel
mailing list