Skip to content

Commit

Permalink
client: Remove the event thread
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
giucam committed Nov 10, 2015
1 parent 4be829e commit eabca26
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 227 deletions.
2 changes: 0 additions & 2 deletions src/client/client.pro
Expand Up @@ -73,7 +73,6 @@ SOURCES += qwaylandintegration.cpp \
qwaylandabstractdecoration.cpp \
qwaylanddecorationfactory.cpp \
qwaylanddecorationplugin.cpp \
qwaylandeventthread.cpp\
qwaylandwindowmanagerintegration.cpp \
qwaylandinputcontext.cpp \
qwaylanddatadevice.cpp \
Expand Down Expand Up @@ -107,7 +106,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 \
Expand Down
40 changes: 23 additions & 17 deletions src/client/qwaylanddisplay.cpp
Expand Up @@ -41,7 +41,6 @@

#include "qwaylanddisplay_p.h"

#include "qwaylandeventthread_p.h"
#include "qwaylandintegration_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandscreen_p.h"
Expand Down Expand Up @@ -141,21 +140,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();
Expand All @@ -166,15 +159,28 @@ QWaylandDisplay::~QWaylandDisplay(void)
qDeleteAll(mScreens);
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();
}

Expand All @@ -185,7 +191,7 @@ void QWaylandDisplay::flushRequests()
void QWaylandDisplay::blockingReadEvents()
{
if (wl_display_dispatch(mDisplay) < 0) {
mEventThreadObject->checkError();
checkError();
exitWithError();
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/client/qwaylanddisplay_p.h
Expand Up @@ -165,6 +165,7 @@ public slots:
private:
void waitForScreens();
void exitWithError();
void checkError() const;

struct Listener {
RegistryListener listener;
Expand All @@ -174,8 +175,6 @@ public slots:
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;
Expand Down
116 changes: 0 additions & 116 deletions src/client/qwaylandeventthread.cpp

This file was deleted.

90 changes: 0 additions & 90 deletions src/client/qwaylandeventthread_p.h

This file was deleted.

5 changes: 5 additions & 0 deletions src/client/qwaylandintegration.cpp
Expand Up @@ -61,6 +61,7 @@
#include <qpa/qplatformcursor.h>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>
#include <QSocketNotifier>

#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatformaccessibility.h>
Expand Down Expand Up @@ -194,6 +195,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
Expand Down

0 comments on commit eabca26

Please sign in to comment.