From 1998d5ac1ad92011505f0e00761ccc618099fa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 10 Nov 2015 08:52:40 +0100 Subject: [PATCH] [wayland] Improve tear-down to not crash if X11 applications are still around We need to destroy the compositor after Xwayland terminated and after the internal Wayland connection is destroyed. This means when destroying the Workspace we may no longer destroy the Compositor at the same time. Also we need to ensure that other tear down functionality doesn't call into the no longer existing internal client connection. With this change kwin doesn't crash when exiting with Wayland and/or X11 windows still open. --- autotests/wayland/kwin_wayland_test.cpp | 4 +++- main.cpp | 4 ---- main_wayland.cpp | 4 +++- main_x11.cpp | 2 ++ plugins/qpa/window.cpp | 5 +++-- wayland_server.cpp | 5 ++++- wayland_server.h | 1 + workspace.cpp | 2 -- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/autotests/wayland/kwin_wayland_test.cpp b/autotests/wayland/kwin_wayland_test.cpp index f2dcaa50eb..676bedc72c 100644 --- a/autotests/wayland/kwin_wayland_test.cpp +++ b/autotests/wayland/kwin_wayland_test.cpp @@ -50,8 +50,8 @@ WaylandTestApplication::WaylandTestApplication(int &argc, char **argv) WaylandTestApplication::~WaylandTestApplication() { - destroyCompositor(); destroyWorkspace(); + waylandServer()->dispatch(); if (x11Connection()) { Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT); destroyAtoms(); @@ -61,6 +61,8 @@ WaylandTestApplication::~WaylandTestApplication() m_xwaylandProcess->terminate(); m_xwaylandProcess->waitForFinished(); } + waylandServer()->destroyInternalConnection(); + destroyCompositor(); } void WaylandTestApplication::performStartup() diff --git a/main.cpp b/main.cpp index db9598a636..1dcfe04c19 100644 --- a/main.cpp +++ b/main.cpp @@ -418,10 +418,6 @@ void Application::destroyWorkspace() void Application::destroyCompositor() { - if (Workspace::self()) { - // compositor is destroyed together with Workspace - return; - } delete Compositor::self(); } diff --git a/main_wayland.cpp b/main_wayland.cpp index 4e4970e4cf..946598f44f 100644 --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -74,8 +74,8 @@ ApplicationWayland::ApplicationWayland(int &argc, char **argv) ApplicationWayland::~ApplicationWayland() { - destroyCompositor(); destroyWorkspace(); + waylandServer()->dispatch(); if (x11Connection()) { Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT); destroyAtoms(); @@ -85,6 +85,8 @@ ApplicationWayland::~ApplicationWayland() m_xwaylandProcess->terminate(); m_xwaylandProcess->waitForFinished(); } + waylandServer()->destroyInternalConnection(); + destroyCompositor(); } void ApplicationWayland::performStartup() diff --git a/main_x11.cpp b/main_x11.cpp index 5cb1f5de6f..2c137431b5 100644 --- a/main_x11.cpp +++ b/main_x11.cpp @@ -121,6 +121,7 @@ ApplicationX11::ApplicationX11(int &argc, char **argv) ApplicationX11::~ApplicationX11() { + destroyCompositor(); destroyWorkspace(); if (!owner.isNull() && owner->ownerWindow() != XCB_WINDOW_NONE) // If there was no --replace (no new WM) Xcb::setInputFocus(XCB_INPUT_FOCUS_POINTER_ROOT); @@ -134,6 +135,7 @@ void ApplicationX11::setReplace(bool replace) void ApplicationX11::lostSelection() { sendPostedEvents(); + destroyCompositor(); destroyWorkspace(); // Remove windowmanager privileges Xcb::selectInput(rootWindow(), XCB_EVENT_MASK_PROPERTY_CHANGE); diff --git a/plugins/qpa/window.cpp b/plugins/qpa/window.cpp index 12a6086b5a..43a3297be2 100644 --- a/plugins/qpa/window.cpp +++ b/plugins/qpa/window.cpp @@ -57,7 +57,6 @@ Window::~Window() } delete m_shellSurface; delete m_surface; - waylandServer()->internalClientConection()->flush(); } WId Window::winId() const @@ -106,7 +105,9 @@ void Window::unmap() } m_surface->attachBuffer(KWayland::Client::Buffer::Ptr()); m_surface->commit(KWayland::Client::Surface::CommitFlag::None); - waylandServer()->internalClientConection()->flush(); + if (waylandServer()->internalClientConection()) { + waylandServer()->internalClientConection()->flush(); + } } void Window::createEglSurface(EGLDisplay dpy, EGLConfig config) diff --git a/wayland_server.cpp b/wayland_server.cpp index bf6ccf9844..f44726c124 100644 --- a/wayland_server.cpp +++ b/wayland_server.cpp @@ -70,13 +70,16 @@ WaylandServer::WaylandServer(QObject *parent) qRegisterMetaType(); } -WaylandServer::~WaylandServer() +WaylandServer::~WaylandServer() = default; + +void WaylandServer::destroyInternalConnection() { if (m_internalConnection.client) { dispatch(); m_internalConnection.client->deleteLater(); m_internalConnection.clientThread->quit(); m_internalConnection.clientThread->wait(); + m_internalConnection.client = nullptr; } } diff --git a/wayland_server.h b/wayland_server.h index e54e39bff0..02d752af31 100644 --- a/wayland_server.h +++ b/wayland_server.h @@ -116,6 +116,7 @@ public: int createInputMethodConnection(); void createInternalConnection(); + void destroyInternalConnection(); void initWorkspace(); KWayland::Server::ClientConnection *xWaylandConnection() const { diff --git a/workspace.cpp b/workspace.cpp index 1fd44e6b31..71c5cd874b 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -425,8 +425,6 @@ void Workspace::init() Workspace::~Workspace() { - delete m_compositor; - m_compositor = NULL; blockStackingUpdates(true); // TODO: grabXServer();