wayland: Fix internal connection teardown

The internal EventQueue is a child of the registry object. This means
that after the registry is destroyed, all proxy objects in that event
queue are going to have invalid reference to it, which is not a problem
as long as the wl_display_dispatch() function is not called.

The wl_display_dispatch() function uses wl_proxy's queue reference to
enqueue incoming events to that queue.

Unfortunately, during teardown, the internal ConnectionThread may
dispatch events right after the registry object has been destroyed,
which can lead to a crash.

In order to fix the crash, we need to destroy all proxy objects and only
after that we can destroy the event queue. It's okay if wayland events
are dispatched in between.
This commit is contained in:
Vlad Zahorodnii 2021-05-13 21:15:06 +03:00
parent 7861c8d389
commit 33b2ea2058
2 changed files with 5 additions and 1 deletions

View file

@ -217,6 +217,7 @@ void WaylandServer::destroyInternalConnection()
delete m_internalConnection.compositor;
delete m_internalConnection.seat;
delete m_internalConnection.ddm;
delete m_internalConnection.eventQueue; // Must be destroyed last.
dispatch();
m_internalConnection.client->deleteLater();
m_internalConnection.clientThread->quit();
@ -721,11 +722,12 @@ void WaylandServer::createInternalConnection()
connect(m_internalConnection.client, &ConnectionThread::connected, this,
[this] {
Registry *registry = new Registry(this);
EventQueue *eventQueue = new EventQueue(registry);
EventQueue *eventQueue = new EventQueue(this);
eventQueue->setup(m_internalConnection.client);
registry->setEventQueue(eventQueue);
registry->create(m_internalConnection.client);
m_internalConnection.registry = registry;
m_internalConnection.eventQueue = eventQueue;
connect(registry, &Registry::interfacesAnnounced, this,
[this, registry] {
m_internalConnection.interfacesAnnounced = true;

View file

@ -23,6 +23,7 @@ namespace KWayland
namespace Client
{
class ConnectionThread;
class EventQueue;
class Registry;
class Compositor;
class Seat;
@ -297,6 +298,7 @@ private:
struct {
KWaylandServer::ClientConnection *server = nullptr;
KWayland::Client::ConnectionThread *client = nullptr;
KWayland::Client::EventQueue *eventQueue = nullptr;
QThread *clientThread = nullptr;
KWayland::Client::Registry *registry = nullptr;
KWayland::Client::Compositor *compositor = nullptr;