Mesa (master): loader/dri3: Check for window destruction in dri3_wait_for_event_locked
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Jun 29 17:30:03 UTC 2020
Module: Mesa
Branch: master
Commit: d7d7687829875e401690219d4a72458fb2bbe4de
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=d7d7687829875e401690219d4a72458fb2bbe4de
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>
---
src/loader/loader_dri3_helper.c | 38 +++++++++++++++++++++++++++++++++++++-
src/loader/loader_dri3_helper.h | 1 +
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 425faba8f64..97b5182994a 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