summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-10-23 13:29:41 +0300
committerGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-11-03 13:13:34 +0000
commit302d4ffb8549214eb4028dc3e47ec4ee4e12ffbd (patch)
treee07afdfbb1bd77a6af579b8dfedf49c174378a04
parent183a6a0effdf1332ec445e5d1626b99d550c79a8 (diff)
client: Remove the event thread
If the compositor sends events to us while the main thread is blocked the socket notifier in the events thread would keep sending out the activated() signal, but no events would actually be read until the main thread starts to run again. That causes the event thread to keep queueing new events, and so allocating memory, potentially forever. This patch fixes the issue in maybe a bit radical way, that is by removing the event thread. The socket notifier now runs in the main thread so it will block if the events are not being read. Nowadays there is no real reason to keep the event thread around, as every thread that needs to receive wayland events can dispatch them on its own, we don't need a central dispatcher thread anymore. Change-Id: Ib7885e4b038b82719d78d193f465618a72cbe6af Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
-rw-r--r--src/client/client.pro2
-rw-r--r--src/client/qwaylanddisplay.cpp42
-rw-r--r--src/client/qwaylanddisplay_p.h3
-rw-r--r--src/client/qwaylandeventthread.cpp112
-rw-r--r--src/client/qwaylandeventthread_p.h97
-rw-r--r--src/client/qwaylandintegration.cpp5
6 files changed, 29 insertions, 232 deletions
diff --git a/src/client/client.pro b/src/client/client.pro
index 7182f3203..8bd9e1dc8 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -78,7 +78,6 @@ SOURCES += qwaylandintegration.cpp \
qwaylandabstractdecoration.cpp \
qwaylanddecorationfactory.cpp \
qwaylanddecorationplugin.cpp \
- qwaylandeventthread.cpp\
qwaylandwindowmanagerintegration.cpp \
qwaylandinputcontext.cpp \
qwaylanddatadevice.cpp \
@@ -111,7 +110,6 @@ HEADERS += qwaylandintegration_p.h \
qwaylandabstractdecoration_p.h \
qwaylanddecorationfactory_p.h \
qwaylanddecorationplugin_p.h \
- qwaylandeventthread_p.h \
qwaylandwindowmanagerintegration_p.h \
qwaylandinputcontext_p.h \
qwaylanddatadevice_p.h \
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index dbb8e12dd..a6f52bc24 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -33,7 +33,6 @@
#include "qwaylanddisplay_p.h"
-#include "qwaylandeventthread_p.h"
#include "qwaylandintegration_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandscreen_p.h"
@@ -145,21 +144,15 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
{
qRegisterMetaType<uint32_t>("uint32_t");
- mEventThreadObject = new QWaylandEventThread(0);
- mEventThread = new QThread(this);
- mEventThread->setObjectName(QStringLiteral("QtWayland"));
- mEventThreadObject->moveToThread(mEventThread);
- mEventThread->start();
-
- mEventThreadObject->displayConnect();
- mDisplay = mEventThreadObject->display(); //blocks until display is available
+ mDisplay = wl_display_connect(NULL);
+ if (mDisplay == NULL) {
+ qErrnoWarning(errno, "Failed to create display");
+ ::exit(1);
+ }
struct ::wl_registry *registry = wl_display_get_registry(mDisplay);
init(registry);
- connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests()));
- connect(mEventThreadObject, &QWaylandEventThread::fatalError, this, &QWaylandDisplay::exitWithError);
-
mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this));
forceRoundTrip();
@@ -175,15 +168,28 @@ QWaylandDisplay::~QWaylandDisplay(void)
}
mScreens.clear();
delete mDndSelectionHandler.take();
- mEventThread->quit();
- mEventThread->wait();
- delete mEventThreadObject;
+ wl_display_disconnect(mDisplay);
+}
+
+void QWaylandDisplay::checkError() const
+{
+ int ecode = wl_display_get_error(mDisplay);
+ if ((ecode == EPIPE || ecode == ECONNRESET)) {
+ // special case this to provide a nicer error
+ qWarning("The Wayland connection broke. Did the Wayland compositor die?");
+ } else {
+ qErrnoWarning(ecode, "The Wayland connection experienced a fatal error");
+ }
}
void QWaylandDisplay::flushRequests()
{
+ if (wl_display_prepare_read(mDisplay) == 0) {
+ wl_display_read_events(mDisplay);
+ }
+
if (wl_display_dispatch_pending(mDisplay) < 0) {
- mEventThreadObject->checkError();
+ checkError();
exitWithError();
}
@@ -194,15 +200,13 @@ void QWaylandDisplay::flushRequests()
void QWaylandDisplay::blockingReadEvents()
{
if (wl_display_dispatch(mDisplay) < 0) {
- mEventThreadObject->checkError();
+ checkError();
exitWithError();
}
}
void QWaylandDisplay::exitWithError()
{
- mEventThread->quit();
- mEventThread->wait();
::exit(1);
}
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index bf48c2123..8262e72be 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -177,6 +177,7 @@ public slots:
private:
void waitForScreens();
void exitWithError();
+ void checkError() const;
struct Listener {
RegistryListener listener;
@@ -186,8 +187,6 @@ private:
struct wl_display *mDisplay;
QtWayland::wl_compositor mCompositor;
struct wl_shm *mShm;
- QThread *mEventThread;
- QWaylandEventThread *mEventThreadObject;
QScopedPointer<QtWayland::wl_shell> mShell;
QScopedPointer<QWaylandXdgShell> mShellXdg;
QList<QWaylandScreen *> mScreens;
diff --git a/src/client/qwaylandeventthread.cpp b/src/client/qwaylandeventthread.cpp
deleted file mode 100644
index e0a3edcb8..000000000
--- a/src/client/qwaylandeventthread.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwaylandeventthread_p.h"
-#include <QtCore/QSocketNotifier>
-#include <QCoreApplication>
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWaylandClient {
-
-QWaylandEventThread::QWaylandEventThread(QObject *parent)
- : QObject(parent)
- , m_display(0)
- , m_fileDescriptor(-1)
- , m_readNotifier(0)
- , m_displayLock(new QMutex)
-{
-}
-
-QWaylandEventThread::~QWaylandEventThread()
-{
- delete m_displayLock;
- wl_display_disconnect(m_display);
-}
-
-void QWaylandEventThread::displayConnect()
-{
- m_displayLock->lock();
- QMetaObject::invokeMethod(this, "waylandDisplayConnect", Qt::QueuedConnection);
-}
-
-// ### be careful what you do, this function may also be called from other
-// threads to clean up & exit.
-void QWaylandEventThread::checkError() const
-{
- int ecode = wl_display_get_error(m_display);
- if ((ecode == EPIPE || ecode == ECONNRESET)) {
- // special case this to provide a nicer error
- qWarning("The Wayland connection broke. Did the Wayland compositor die?");
- } else {
- qErrnoWarning(ecode, "The Wayland connection experienced a fatal error");
- }
-}
-
-void QWaylandEventThread::readWaylandEvents()
-{
- if (wl_display_prepare_read(m_display) == 0) {
- wl_display_read_events(m_display);
- }
- emit newEventsRead();
-}
-
-void QWaylandEventThread::waylandDisplayConnect()
-{
- m_display = wl_display_connect(NULL);
- if (m_display == NULL) {
- qErrnoWarning(errno, "Failed to create display");
- ::exit(1);
- }
- m_displayLock->unlock();
-
- m_fileDescriptor = wl_display_get_fd(m_display);
-
- m_readNotifier = new QSocketNotifier(m_fileDescriptor, QSocketNotifier::Read, this);
- connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readWaylandEvents()));
-}
-
-wl_display *QWaylandEventThread::display() const
-{
- QMutexLocker displayLock(m_displayLock);
- return m_display;
-}
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/client/qwaylandeventthread_p.h b/src/client/qwaylandeventthread_p.h
deleted file mode 100644
index 0920d403e..000000000
--- a/src/client/qwaylandeventthread_p.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QWAYLANDEVENTTHREAD_H
-#define QWAYLANDEVENTTHREAD_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QObject>
-#include <QMutex>
-#include <wayland-client.h>
-
-#include <QtWaylandClient/private/qwaylandclientexport_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QSocketNotifier;
-
-namespace QtWaylandClient {
-
-class Q_WAYLAND_CLIENT_EXPORT QWaylandEventThread : public QObject
-{
- Q_OBJECT
-public:
- explicit QWaylandEventThread(QObject *parent = 0);
- ~QWaylandEventThread();
-
- void displayConnect();
-
- wl_display *display() const;
-
- void checkError() const;
-
-private slots:
- void readWaylandEvents();
-
- void waylandDisplayConnect();
-
-signals:
- void newEventsRead();
- void fatalError();
-
-private:
-
- struct wl_display *m_display;
- int m_fileDescriptor;
-
- QSocketNotifier *m_readNotifier;
-
- QMutex *m_displayLock;
-
-};
-
-}
-
-QT_END_NAMESPACE
-
-#endif // QWAYLANDEVENTTHREAD_H
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 82df8a30a..39fff533d 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -54,6 +54,7 @@
#include <qpa/qplatformcursor.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>
+#include <QSocketNotifier>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
@@ -201,6 +202,10 @@ void QWaylandIntegration::initialize()
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests()));
QObject::connect(dispatcher, SIGNAL(awake()), mDisplay, SLOT(flushRequests()));
+
+ int fd = wl_display_get_fd(mDisplay->wl_display());
+ QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay);
+ QObject::connect(sn, SIGNAL(activated(int)), mDisplay, SLOT(flushRequests()));
}
QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const