Mesa (staging/20.1): loader/dri3: Check for window destruction in dri3_wait_for_event_locked
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jun 29 19:14:58 UTC 2020
Module: Mesa
Branch: staging/20.1
Commit: 195dd044617707d680b412a08549f68cc3551c53
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=195dd044617707d680b412a08549f68cc3551c53
Author: Michel Dänzer <mdaenzer at redhat.com>
Date: Fri Jun 5 19:07:55 2020 +0200
loader/dri3: Check for window destruction in dri3_wait_for_event_locked
If the underlying X11 window gets destroyed, the event we're waiting
for may never be delivered, in which case xcb_wait_for_special_event
would hang indefinitely.
Solution:
1. Use xcb_poll_for_special_event to check if an event has arrived yet.
2. If not, Wait up to ~1s for XCB's file descriptor to become readable;
if it does, go back to step 1.
3. If the file descriptor didn't become readable, make a round-trip to
the X server to check that the window still exists. Go back to step
1 if it does, otherwise bail.
Also add an early bail-out when it's known that the window was
destroyed.
Cc: mesa-stable
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/116
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5368>
(cherry picked from commit d7d7687829875e401690219d4a72458fb2bbe4de)
---
.pick_status.json | 2 +-
src/loader/loader_dri3_helper.c | 38 +++++++++++++++++++++++++++++++++++++-
src/loader/loader_dri3_helper.h | 1 +
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/.pick_status.json b/.pick_status.json
index 22b5611bd17..10081f37edc 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -4,7 +4,7 @@
"description": "loader/dri3: Check for window destruction in dri3_wait_for_event_locked",
"nominated": true,
"nomination_type": 0,
- "resolution": 0,
+ "resolution": 1,
"master_sha": null,
"because_sha": null
},
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 12860d6594f..81c67403517 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -22,6 +22,7 @@
*/
#include <fcntl.h>
+#include <poll.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -532,20 +533,55 @@ dri3_wait_for_event_locked(struct loader_dri3_drawable *draw,
xcb_generic_event_t *ev;
xcb_present_generic_event_t *ge;
+ if (draw->window_destroyed)
+ return false;
+
xcb_flush(draw->conn);
/* Only have one thread waiting for events at a time */
if (draw->has_event_waiter) {
cnd_wait(&draw->event_cnd, &draw->mtx);
+ if (draw->window_destroyed)
+ return false;
if (full_sequence)
*full_sequence = draw->last_special_event_sequence;
/* Another thread has updated the protected info, so retest. */
return true;
} else {
+ struct pollfd pfds;
+
draw->has_event_waiter = true;
/* Allow other threads access to the drawable while we're waiting. */
mtx_unlock(&draw->mtx);
- ev = xcb_wait_for_special_event(draw->conn, draw->special_event);
+
+ pfds.fd = xcb_get_file_descriptor(draw->conn);
+ pfds.events = POLLIN;
+
+ ev = xcb_poll_for_special_event(draw->conn, draw->special_event);
+ while (!ev) {
+ /* Wait up to ~1s for the XCB FD to become readable */
+ if (poll(&pfds, 1, 1000) < 1) {
+ xcb_get_window_attributes_cookie_t cookie;
+ xcb_get_window_attributes_reply_t *attrib;
+ xcb_generic_error_t *error;
+
+ /* Check if the window still exists */
+ cookie = xcb_get_window_attributes(draw->conn, draw->drawable);
+ attrib = xcb_get_window_attributes_reply(draw->conn, cookie, &error);
+ free(attrib);
+
+ if (error) {
+ if (error->error_code == BadWindow)
+ draw->window_destroyed = true;
+
+ free(error);
+ break;
+ }
+ }
+
+ ev = xcb_poll_for_special_event(draw->conn, draw->special_event);
+ }
+
mtx_lock(&draw->mtx);
draw->has_event_waiter = false;
cnd_broadcast(&draw->event_cnd);
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index c314e4c5a9d..0961534a792 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -122,6 +122,7 @@ struct loader_dri3_drawable {
uint8_t have_back;
uint8_t have_fake_front;
uint8_t is_pixmap;
+ bool window_destroyed;
/* Information about the GPU owning the buffer */
__DRIscreen *dri_screen;
More information about the mesa-commit
mailing list