From 8cc88f4854b72bb270e4b701d15ada7bdbb74ff4 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Wed, 17 Jun 2015 14:48:44 +0300 Subject: Fix possible race condition leading to a dead lock It is a bit dangerous to call wl_display_dispatch() in the event thread, since it may race with the dispatch called e.g. in QWaylandDisplay's blockingReadEvents() and lead to a dead lock. Instead, use wl_display_prepare_read() and wl_display_read_events() in the event thread, which doesn't block, and only dispatch in QWaylandDisplay. As a result we don't need the additional wayland queue anymore, so remove it. Change-Id: I9fbbe5d2f38d06773beb7847df1a0212cca92c37 Reviewed-by: Robin Burchell --- examples/wayland/server-buffer/client/main.cpp | 1 - src/client/qwaylanddisplay.cpp | 14 ++++---------- src/client/qwaylanddisplay_p.h | 2 -- src/client/qwaylandeventthread.cpp | 8 ++------ src/client/qwaylandnativeinterface.cpp | 2 -- 5 files changed, 6 insertions(+), 21 deletions(-) diff --git a/examples/wayland/server-buffer/client/main.cpp b/examples/wayland/server-buffer/client/main.cpp index 3f7a94d03..1a2c447a7 100644 --- a/examples/wayland/server-buffer/client/main.cpp +++ b/examples/wayland/server-buffer/client/main.cpp @@ -95,7 +95,6 @@ public: QtWaylandClient::QWaylandDisplay *wayland_display = wayland_integration->display(); struct ::wl_registry *registry = wl_display_get_registry(wayland_display->wl_display()); - wl_proxy_set_queue(reinterpret_cast(registry), wayland_display->wl_event_queue()); QtWayland::wl_registry::init(registry); } diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index eb431cf0d..f197b3788 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -147,12 +147,7 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) mEventThreadObject->displayConnect(); mDisplay = mEventThreadObject->display(); //blocks until display is available - //Create a new even queue for the QtGui thread - mEventQueue = wl_display_create_queue(mDisplay); - struct ::wl_registry *registry = wl_display_get_registry(mDisplay); - wl_proxy_set_queue((struct wl_proxy *)registry, mEventQueue); - init(registry); connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests())); @@ -180,7 +175,7 @@ QWaylandDisplay::~QWaylandDisplay(void) void QWaylandDisplay::flushRequests() { - if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) { + if (wl_display_dispatch_pending(mDisplay) < 0) { mEventThreadObject->checkError(); exitWithError(); } @@ -191,7 +186,7 @@ void QWaylandDisplay::flushRequests() void QWaylandDisplay::blockingReadEvents() { - if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) { + if (wl_display_dispatch(mDisplay) < 0) { mEventThreadObject->checkError(); exitWithError(); } @@ -345,17 +340,16 @@ void QWaylandDisplay::forceRoundTrip() int ret = 0; bool done = false; wl_callback *callback = wl_display_sync(mDisplay); - wl_proxy_set_queue((struct wl_proxy *)callback, mEventQueue); wl_callback_add_listener(callback, &sync_listener, &done); flushRequests(); if (QThread::currentThread()->eventDispatcher()) { while (!done && ret >= 0) { QThread::currentThread()->eventDispatcher()->processEvents(QEventLoop::WaitForMoreEvents); - ret = wl_display_dispatch_queue_pending(mDisplay, mEventQueue); + ret = wl_display_dispatch_pending(mDisplay); } } else { while (!done && ret >= 0) - ret = wl_display_dispatch_queue(mDisplay, mEventQueue); + ret = wl_display_dispatch(mDisplay); } if (ret == -1 && !done) diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 7ba431d7c..ee129a50e 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -108,7 +108,6 @@ public: void setCursor(struct wl_buffer *buffer, struct wl_cursor_image *image); struct wl_display *wl_display() const { return mDisplay; } - struct wl_event_queue *wl_event_queue() const { return mEventQueue; } struct ::wl_registry *wl_registry() { return object(); } const struct wl_compositor *wl_compositor() const { return mCompositor.object(); } @@ -175,7 +174,6 @@ private: }; struct wl_display *mDisplay; - struct wl_event_queue *mEventQueue; QtWayland::wl_compositor mCompositor; struct wl_shm *mShm; QThread *mEventThread; diff --git a/src/client/qwaylandeventthread.cpp b/src/client/qwaylandeventthread.cpp index e2e21c9e7..e0a3edcb8 100644 --- a/src/client/qwaylandeventthread.cpp +++ b/src/client/qwaylandeventthread.cpp @@ -80,13 +80,9 @@ void QWaylandEventThread::checkError() const void QWaylandEventThread::readWaylandEvents() { - if (wl_display_dispatch(m_display) < 0) { - checkError(); - m_readNotifier->setEnabled(false); - emit fatalError(); - return; + if (wl_display_prepare_read(m_display) == 0) { + wl_display_read_events(m_display); } - emit newEventsRead(); } diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp index 8170c39f1..0d20075f0 100644 --- a/src/client/qwaylandnativeinterface.cpp +++ b/src/client/qwaylandnativeinterface.cpp @@ -58,8 +58,6 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re if (lowerCaseResource == "display" || lowerCaseResource == "wl_display" || lowerCaseResource == "nativedisplay") return m_integration->display()->wl_display(); - if (lowerCaseResource == "wl_event_queue") - return m_integration->display()->wl_event_queue(); if (lowerCaseResource == "compositor") return const_cast(m_integration->display()->wl_compositor()); if (lowerCaseResource == "server_buffer_integration") -- cgit v1.2.3