summaryrefslogtreecommitdiff
path: root/src/XlibInt.c
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2017-03-24 11:07:36 -0400
committerAdam Jackson <ajax@redhat.com>2019-01-16 11:45:34 -0500
commit5538b3e4ae6dee32c47db9dfc85b07bbe7b90f6c (patch)
treee8e6745efcdffaf92d4ac2c5cef0c493fd67788e /src/XlibInt.c
parent6d2cde9633b5ee020cb60caea1cf61e090b86dd2 (diff)
downloadxorg-lib-libX11-5538b3e4ae6dee32c47db9dfc85b07bbe7b90f6c.tar.gz
_XDefaultIOError: Do better at detecting explicit shutdown
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, since the socket is non-blocking. In this case, check whether the socket has any more data to read, and if not treat it like EPIPE. Signed-off-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'src/XlibInt.c')
-rw-r--r--src/XlibInt.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/XlibInt.c b/src/XlibInt.c
index 903e47f3..dd39445b 100644
--- a/src/XlibInt.c
+++ b/src/XlibInt.c
@@ -50,6 +50,8 @@ from The Open Group.
#ifdef XTHREADS
#include "locking.h"
+#include <sys/ioctl.h>
+
/* these pointers get initialized by XInitThreads */
LockInfoPtr _Xglobal_lock = NULL;
void (*_XCreateMutex_fn)(LockInfoPtr) = NULL;
@@ -1234,6 +1236,21 @@ _XWireToEvent(
return(True);
}
+static int
+SocketBytesReadable(Display *dpy)
+{
+ int bytes = 0, last_error;
+#ifdef WIN32
+ last_error = WSAGetLastError();
+ ioctlsocket(ConnectionNumber(dpy), FIONREAD, &bytes);
+ WSASetLastError(last_error);
+#else
+ last_error = errno;
+ ioctl(ConnectionNumber(dpy), FIONREAD, &bytes);
+ errno = last_error;
+#endif
+ return bytes;
+}
/*
* _XDefaultIOError - Default fatal system error reporting routine. Called
@@ -1242,7 +1259,17 @@ _XWireToEvent(
_X_NORETURN int _XDefaultIOError(
Display *dpy)
{
- if (ECHECK(EPIPE)) {
+ int killed = ECHECK(EPIPE);
+
+ /*
+ * If the socket was closed on the far end, the final recvmsg in
+ * xcb will have thrown EAGAIN because we're non-blocking. Detect
+ * this to get the more informative error message.
+ */
+ if (ECHECK(EAGAIN) && SocketBytesReadable(dpy) <= 0)
+ killed = True;
+
+ if (killed) {
fprintf (stderr,
"X connection to %s broken (explicit kill or server shutdown).\r\n",
DisplayString (dpy));