[PATCH wayland 4/4] client: Fix wl_display_roundtrip_queue() race condition

Jonas Ådahl jadahl at gmail.com
Wed Apr 27 07:37:41 UTC 2016


Without this commit, wl_display_roundtrip_queue() is vulnerable to a
race condition, causing the callback to be dispatched on the wrong
queue.

The race condition happens if some non-main thread calls
wl_display_roundtrip_queue() with its thread local queue, and the main
thread reads and dispatches the callback event from the
wl_display_sync() call before the thread local queue is set.

The issue is fixed by using a proxy wrapper, making the initialization
of the callback proxy atomic, effectively making it no longer possible
for some other thread to dispatch the proxy before the correct thread
local queue is set.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 src/wayland-client.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 6de91cd..cb5213b 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1106,14 +1106,20 @@ static const struct wl_callback_listener sync_listener = {
 WL_EXPORT int
 wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue)
 {
+	struct wl_display *display_wrapper;
 	struct wl_callback *callback;
 	int done, ret = 0;
 
 	done = 0;
-	callback = wl_display_sync(display);
+
+	display_wrapper = wl_proxy_create_wrapper(display);
+	wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
+	callback = wl_display_sync(display_wrapper);
+	wl_proxy_wrapper_destroy(display_wrapper);
+
 	if (callback == NULL)
 		return -1;
-	wl_proxy_set_queue((struct wl_proxy *) callback, queue);
+
 	wl_callback_add_listener(callback, &sync_listener, &done);
 	while (!done && ret >= 0)
 		ret = wl_display_dispatch_queue(display, queue);
-- 
2.5.5



More information about the wayland-devel mailing list