From 233d7b7f1f03ef18bf3955eb1f20421e745d22f0 Mon Sep 17 00:00:00 2001 From: Thomas Anderson Date: Wed, 2 Dec 2020 00:25:42 +0000 Subject: Fix hang in xcb_request_check() This fixes https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/53 The issue was that libxcb expected to get a reply based on the request_expected variable, but a reply would never arrive because the request was never actually written. To resolve this, a separate request_expected_written variable is added. --- src/xcb_in.c | 13 +++++++++---- src/xcb_out.c | 2 ++ src/xcbint.h | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/xcb_in.c b/src/xcb_in.c index 7d02e9b..4862464 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -736,11 +736,16 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co return 0; pthread_mutex_lock(&c->iolock); request = widen(c, cookie.sequence); - if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected) - && XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed)) + if (XCB_SEQUENCE_COMPARE(request, >, c->in.request_completed)) { - _xcb_out_send_sync(c); - _xcb_out_flush_to(c, c->out.request); + if(XCB_SEQUENCE_COMPARE(request, >=, c->in.request_expected)) + { + _xcb_out_send_sync(c); + } + if (XCB_SEQUENCE_COMPARE(request, >=, c->out.request_expected_written)) + { + _xcb_out_flush_to(c, c->out.request); + } } reply = wait_for_reply(c, request, &ret); assert(!reply); diff --git a/src/xcb_out.c b/src/xcb_out.c index df94867..8ffc03f 100644 --- a/src/xcb_out.c +++ b/src/xcb_out.c @@ -447,6 +447,7 @@ int _xcb_out_init(_xcb_out *out) out->request = 0; out->request_written = 0; + out->request_expected_written = 0; if(pthread_mutex_init(&out->reqlenlock, 0)) return 0; @@ -467,6 +468,7 @@ int _xcb_out_send(xcb_connection_t *c, struct iovec *vector, int count) while(ret && count) ret = _xcb_conn_wait(c, &c->out.cond, &vector, &count); c->out.request_written = c->out.request; + c->out.request_expected_written = c->in.request_expected; pthread_cond_broadcast(&c->out.cond); _xcb_in_wake_up_next_reader(c); return ret; diff --git a/src/xcbint.h b/src/xcbint.h index 6a070f8..235c848 100644 --- a/src/xcbint.h +++ b/src/xcbint.h @@ -113,6 +113,7 @@ typedef struct _xcb_out { uint64_t request; uint64_t request_written; + uint64_t request_expected_written; uint64_t total_written; pthread_mutex_t reqlenlock; -- cgit v1.2.3