We have to block other threads from reading events. Otherwise other threads may assign done event to the default queue, if they call wl_display_read_events before setting the queue for the callback proxy. This would cause a deadlock in wl_display_dispatch_queue, because the default queue is not dispatched.
We can call wl_display_prepare_read_queue API which blocks on success other threads from reading events and call wl_display_cancel read after the queue is set to the proxy. This new implementation ensures thread safety for the API. Signed-off-by: Emre Ucan <[email protected]> --- src/wayland-client.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/wayland-client.c b/src/wayland-client.c index ef12bfc..00d8cda 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -1075,12 +1075,26 @@ wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *qu struct wl_callback *callback; int done, ret = 0; + /*We have to block other threads from reading events. Otherwise other threads + * may assign done event to the default queue, if they call wl_display_read_events + * before setting the queue for the callback proxy. This would cause a deadlock + * in wl_display_dispatch_queue, because the default queue is not dispatched.*/ + while (ret >= 0 && wl_display_prepare_read_queue(display, queue)) + ret = wl_display_dispatch_queue_pending(display, queue); + + if (ret < 0) + return ret; + done = 0; callback = wl_display_sync(display); - if (callback == NULL) + if (callback == NULL) { + wl_display_cancel_read(display); return -1; + } + wl_proxy_set_queue((struct wl_proxy *) callback, queue); wl_callback_add_listener(callback, &sync_listener, &done); + wl_display_cancel_read(display); while (!done && ret >= 0) ret = wl_display_dispatch_queue(display, queue); -- 1.7.9.5 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
