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 --- src/client/qwaylanddisplay.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'src/client/qwaylanddisplay.cpp') 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) -- cgit v1.2.3 From cf91dd10ff02916bace9281b0bfce02933e92814 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 25 Sep 2015 10:07:34 +0300 Subject: Fix a segfault when the wayland connection is broken When calling ::exit() the socket notifier in the events thread may still fire before the process actually exits, using objects that are being destroyed and resulting in a segfault. Stop the events thread before calling ::exit(). Change-Id: I187762da2a7efa83db1e62b0e28dfab89f478c7d Reviewed-by: Pier Luigi Fiorini --- src/client/qwaylanddisplay.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/client/qwaylanddisplay.cpp') diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index f197b3788..0bea9af65 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -194,6 +194,8 @@ void QWaylandDisplay::blockingReadEvents() void QWaylandDisplay::exitWithError() { + mEventThread->quit(); + mEventThread->wait(); ::exit(1); } -- cgit v1.2.3