Blame SOURCES/0002-_XDefaultIOError-Do-better-at-detecting-explicit-shu.patch

96c0cb
From 5538b3e4ae6dee32c47db9dfc85b07bbe7b90f6c Mon Sep 17 00:00:00 2001
96c0cb
From: Adam Jackson <ajax@redhat.com>
96c0cb
Date: Fri, 24 Mar 2017 11:07:36 -0400
96c0cb
Subject: [PATCH 2/2] _XDefaultIOError: Do better at detecting explicit
96c0cb
 shutdown
96c0cb
96c0cb
Currently, when the X server crashes or a client is disconnected with
96c0cb
XKillClient, you get a somewhat confusing error message from libX11
96c0cb
along the lines of:
96c0cb
96c0cb
XIO:  fatal IO error 11 (Resource temporarily unavailable) on X server ":0"
96c0cb
      after 98 requests (40 known processed) with 0 events remaining.
96c0cb
96c0cb
What's happening here is the previous recvmsg has thrown EAGAIN, since
96c0cb
the socket is non-blocking. In this case, check whether the socket has
96c0cb
any more data to read, and if not treat it like EPIPE.
96c0cb
96c0cb
Signed-off-by: Adam Jackson <ajax@redhat.com>
96c0cb
---
96c0cb
 src/XlibInt.c | 29 ++++++++++++++++++++++++++++-
96c0cb
 1 file changed, 28 insertions(+), 1 deletion(-)
96c0cb
96c0cb
diff --git a/src/XlibInt.c b/src/XlibInt.c
96c0cb
index 903e47f3..dd39445b 100644
96c0cb
--- a/src/XlibInt.c
96c0cb
+++ b/src/XlibInt.c
96c0cb
@@ -50,6 +50,8 @@ from The Open Group.
96c0cb
 #ifdef XTHREADS
96c0cb
 #include "locking.h"
96c0cb
 
96c0cb
+#include <sys/ioctl.h>
96c0cb
+
96c0cb
 /* these pointers get initialized by XInitThreads */
96c0cb
 LockInfoPtr _Xglobal_lock = NULL;
96c0cb
 void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
96c0cb
@@ -1234,6 +1236,21 @@ _XWireToEvent(
96c0cb
 	return(True);
96c0cb
 }
96c0cb
 
96c0cb
+static int
96c0cb
+SocketBytesReadable(Display *dpy)
96c0cb
+{
96c0cb
+    int bytes = 0, last_error;
96c0cb
+#ifdef WIN32
96c0cb
+    last_error = WSAGetLastError();
96c0cb
+    ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
96c0cb
+    WSASetLastError(last_error);
96c0cb
+#else
96c0cb
+    last_error = errno;
96c0cb
+    ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
96c0cb
+    errno = last_error;
96c0cb
+#endif
96c0cb
+    return bytes;
96c0cb
+}
96c0cb
 
96c0cb
 /*
96c0cb
  * _XDefaultIOError - Default fatal system error reporting routine.  Called
96c0cb
@@ -1242,7 +1259,17 @@ _XWireToEvent(
96c0cb
 _X_NORETURN int _XDefaultIOError(
96c0cb
 	Display *dpy)
96c0cb
 {
96c0cb
-	if (ECHECK(EPIPE)) {
96c0cb
+	int killed = ECHECK(EPIPE);
96c0cb
+
96c0cb
+	/*
96c0cb
+	 * If the socket was closed on the far end, the final recvmsg in
96c0cb
+	 * xcb will have thrown EAGAIN because we're non-blocking. Detect
96c0cb
+	 * this to get the more informative error message.
96c0cb
+	 */
96c0cb
+	if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
96c0cb
+	    killed = True;
96c0cb
+
96c0cb
+	if (killed) {
96c0cb
 	    fprintf (stderr,
96c0cb
                      "X connection to %s broken (explicit kill or server shutdown).\r\n",
96c0cb
                      DisplayString (dpy));
96c0cb
-- 
96c0cb
2.21.0
96c0cb