Commit 3c04d529 authored by Martin Flöser's avatar Martin Flöser
Browse files

Handle situation of no XDG_RUNTIME_DIR gracefully

Summary:
If KWin fails to start the Wayland server due to XDG_RUNTIME_DIR not
being set, kwin_wayland should terminate with an error condition but
not crash.

This change makes sure that KWin detects that the Wayland server does
not work and terminates the startup early and ensures that it doesn't
crash while going down.

An error message is shown that we could not create the Wayland server.

Test Plan:
Test case added which verifies that WaylandServer fails to
init. Manual testing that kwin_wayland exits with error 1.

Reviewers: #kwin, #plasma_on_wayland

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2078
parent 76fa3026
......@@ -35,6 +35,7 @@ integrationTest(NAME testShellClient SRCS shell_client_test.cpp)
integrationTest(NAME testDontCrashNoBorder SRCS dont_crash_no_border.cpp)
integrationTest(NAME testXClipboardSync SRCS xclipboardsync_test.cpp)
integrationTest(NAME testSceneQPainter SRCS scene_qpainter_test.cpp)
integrationTest(NAME testNoXdgRuntimeDir SRCS no_xdg_runtime_dir_test.cpp)
if (XCB_ICCCM_FOUND)
integrationTest(NAME testMoveResize SRCS move_resize_window_test.cpp LIBS XCB::ICCCM)
......
......@@ -61,7 +61,7 @@ void DebugConsoleTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -123,7 +123,7 @@ void DecorationInputTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
// change some options
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
......
......@@ -60,7 +60,7 @@ void DontCrashAuroraeDestroyDecoTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("org.kde.kdecoration2").writeEntry("library", "org.kde.kwin.aurorae");
......
......@@ -60,7 +60,7 @@ void DontCrashCancelAnimationFromAnimationEndedTest::initTestCase()
qRegisterMetaType<KWin::ShellClient*>();
qRegisterMetaType<KWin::AbstractClient*>();
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(Compositor::self());
QSignalSpy compositorToggledSpy(Compositor::self(), &Compositor::compositingToggled);
......
......@@ -57,7 +57,7 @@ void DontCrashEmptyDecorationTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
// this test needs to enforce OpenGL compositing to get into the crashy condition
qputenv("KWIN_COMPOSE", QByteArrayLiteral("O2"));
......
......@@ -47,7 +47,7 @@ void DontCrashGlxgearsTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
}
......
......@@ -63,7 +63,7 @@ void DontCrashNoBorder::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
config->group("org.kde.kdecoration2").writeEntry("NoPlugin", true);
......
......@@ -68,7 +68,7 @@ void InputStackingOrderTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -159,7 +159,7 @@ void InternalWindowTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -186,7 +186,7 @@ void LockScreenTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -61,7 +61,7 @@ void TestMaximized::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -79,7 +79,7 @@ void MoveResizeWindowTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
QCOMPARE(screens()->count(), 1);
......
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2016 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "kwin_wayland_test.h"
#include "wayland_server.h"
using namespace KWin;
static const QString s_socketName = QStringLiteral("wayland_test_kwin_no_xdg_runtime_dir-0");
class NoXdgRuntimeDirTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void testInitFails();
};
void NoXdgRuntimeDirTest::initTestCase()
{
qunsetenv("XDG_RUNTIME_DIR");
}
void NoXdgRuntimeDirTest::testInitFails()
{
// this test verifies that without an XDG_RUNTIME_DIR the WaylandServer fials to init
QVERIFY(!waylandServer()->init(s_socketName.toLocal8Bit()));
}
WAYLANDTEST_MAIN(NoXdgRuntimeDirTest)
#include "no_xdg_runtime_dir_test.moc"
......@@ -62,7 +62,7 @@ void PlasmaSurfaceTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
}
......
......@@ -76,7 +76,7 @@ void PlasmaWindowTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -40,7 +40,7 @@ void PlatformCursorTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
}
......
......@@ -87,7 +87,7 @@ void PointerInputTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
......
......@@ -72,7 +72,7 @@ void QuickTilingTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
// set custom config which disables the Outline
KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
......
......@@ -62,7 +62,7 @@ void SceneQPainterTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
// disable all effects - we don't want to have it interact with the rendering
auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
......
......@@ -55,7 +55,7 @@ void ShadeTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -56,7 +56,7 @@ void TestShellClient::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -50,7 +50,7 @@ void StartTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
}
......
......@@ -74,7 +74,7 @@ void StrutsTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -61,7 +61,7 @@ void TouchInputTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -51,7 +51,7 @@ void TransientNoInputTest::initTestCase()
QSignalSpy workspaceCreatedSpy(kwinApp(), &Application::workspaceCreated);
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
}
......
......@@ -73,7 +73,7 @@ void TransientPlacementTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -56,7 +56,7 @@ void XClipboardSyncTest::initTestCase()
QVERIFY(workspaceCreatedSpy.isValid());
kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024));
QMetaObject::invokeMethod(kwinApp()->platform(), "setOutputCount", Qt::DirectConnection, Q_ARG(int, 2));
waylandServer()->init(s_socketName.toLocal8Bit());
QVERIFY(waylandServer()->init(s_socketName.toLocal8Bit()));
kwinApp()->start();
QVERIFY(workspaceCreatedSpy.wait());
......
......@@ -90,7 +90,9 @@ ApplicationWayland::~ApplicationWayland()
return;
}
kwinApp()->platform()->setOutputsEnabled(false);
if (kwinApp()->platform()) {
kwinApp()->platform()->setOutputsEnabled(false);
}
// need to unload all effects prior to destroying X connection as they might do X calls
if (effects) {
static_cast<EffectsHandlerImpl*>(effects)->unloadAllEffects();
......@@ -710,7 +712,10 @@ int main(int argc, char * argv[])
if (parser.isSet(screenLockerOption)) {
flags = KWin::WaylandServer::InitalizationFlag::LockScreen;
}
server->init(parser.value(waylandSocketOption).toUtf8(), flags);
if (!server->init(parser.value(waylandSocketOption).toUtf8(), flags)) {
std::cerr << "FATAL ERROR: could not create Wayland server" << std::endl;
return 1;
}
a.initPlatform(*pluginIt);
if (!a.platform()) {
......
......@@ -113,7 +113,7 @@ void WaylandServer::terminateClientConnections()
}
}
void WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
bool WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
{
m_initFlags = flags;
m_display = new KWayland::Server::Display(this);
......@@ -121,6 +121,9 @@ void WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
m_display->setSocketName(QString::fromUtf8(socketName));
}
m_display->start();
if (!m_display->isRunning()) {
return false;
}
m_compositor = m_display->createCompositor(m_display);
m_compositor->create();
connect(m_compositor, &CompositorInterface::surfaceCreated, this,
......@@ -264,6 +267,8 @@ void WaylandServer::init(const QByteArray &socketName, InitalizationFlags flags)
m_outputManagement->create();
m_display->createSubCompositor(m_display)->create();
return true;
}
void WaylandServer::shellClientShown(Toplevel *t)
......
......@@ -77,7 +77,7 @@ public:
Q_DECLARE_FLAGS(InitalizationFlags, InitalizationFlag)
virtual ~WaylandServer();
void init(const QByteArray &socketName = QByteArray(), InitalizationFlags flags = InitalizationFlag::NoOptions);
bool init(const QByteArray &socketName = QByteArray(), InitalizationFlags flags = InitalizationFlag::NoOptions);
void terminateClientConnections();
KWayland::Server::Display *display() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment