[Xcb] [PATCH] _xcb_conn_wait(): Do better at detecting closed sockets

Adam Jackson ajax at redhat.com
Thu Oct 13 15:02:46 UTC 2016


Currently, when the X server crashes or a client is disconnected with
XKillClient, you get a somewhat confusing error message from libX11
along the lines of:

XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
      after 98 requests (40 known processed) with 0 events remaining.

What's happening here is the previous recvmsg has thrown EAGAIN, and
since errno is not cleared on success that's the errno that the I/O
error handler sees.

To fix this, check for POLLHUP explicitly, and if there's no more data
in the socket buffer to read, treat that as an error. We coerce errno to
EPIPE in this case, which triggers the existing EPIPE path in libX11 and
thus generates the much more honest error message:

X connection to :0 broken (explicit kill or server shutdown).

Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 src/xcb_conn.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/src/xcb_conn.c b/src/xcb_conn.c
index 7d09637..ad94443 100644
--- a/src/xcb_conn.c
+++ b/src/xcb_conn.c
@@ -45,6 +45,7 @@
 #elif !defined _WIN32
 #include <sys/select.h>
 #endif
+#include <sys/ioctl.h>
 
 #ifdef _WIN32
 #include "xcb_windefs.h"
@@ -451,7 +452,7 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
 #if USE_POLL
     memset(&fd, 0, sizeof(fd));
     fd.fd = c->fd;
-    fd.events = POLLIN;
+    fd.events = POLLIN | POLLHUP;
 #else
     FD_ZERO(&rfds);
     FD_SET(c->fd, &rfds);
@@ -484,6 +485,19 @@ int _xcb_conn_wait(xcb_connection_t *c, pthread_cond_t *cond, struct iovec **vec
             ret = -1;
             break;
         }
+
+	/* hangup with no data left to read is an error */
+	if (fd.revents & POLLHUP)
+	{
+	    int unread = -1;
+	    ioctl(c->fd, FIONREAD, &unread);
+	    if (unread <= 0)
+	    {
+		/* coerce errno to not be EAGAIN */
+		errno = EPIPE;
+		ret = -1;
+	    }
+	}
 #else
         ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
 #endif
-- 
2.9.3



More information about the Xcb mailing list