From 34982850e2938b924a16e06ab9f4275089de7c4b Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Fri, 30 Oct 2020 15:36:24 +0200 Subject: [PATCH] Destroy all clients before destroying wl_display One of the most disappointing things when writing autotests is dealing with a race condition where destructor requests are processed after all globals have been destroyed. With this change, the Display object will destroy all clients and their resources before destroying the wl_display object. The good thing about doing so is that shut down logic becomes simple. We don't have to assume that wl_resource objects can outlive their wl_global objects, etc. The bad thing is that it exposed a couple of pre-existing latent bugs in the data device and the xdg foreign code. closes plasma/kwayland-server#2 --- src/wayland/autotests/client/test_error.cpp | 5 +- .../autotests/client/test_fake_input.cpp | 4 +- src/wayland/autotests/client/test_idle.cpp | 6 +- .../client/test_plasma_window_model.cpp | 6 +- .../client/test_pointer_constraints.cpp | 8 +- .../autotests/client/test_selection.cpp | 7 +- src/wayland/autotests/client/test_shadow.cpp | 6 +- .../autotests/client/test_text_input_v2.cpp | 8 +- .../autotests/client/test_wayland_blur.cpp | 6 +- .../client/test_wayland_contrast.cpp | 6 +- .../autotests/client/test_wayland_output.cpp | 6 +- .../client/test_wayland_outputmanagement.cpp | 7 +- .../autotests/client/test_wayland_seat.cpp | 22 +-- .../autotests/client/test_wayland_surface.cpp | 10 +- .../client/test_wayland_windowmanagement.cpp | 9 +- .../autotests/client/test_xdg_foreign.cpp | 5 +- .../autotests/client/test_xdg_shell.cpp | 12 +- .../server/test_datacontrol_interface.cpp | 6 +- src/wayland/autotests/server/test_seat.cpp | 13 -- src/wayland/display.cpp | 163 +++++------------- src/wayland/display.h | 1 - src/wayland/server/global.cpp | 13 ++ src/wayland/server/global_p.h | 9 +- 23 files changed, 135 insertions(+), 203 deletions(-) diff --git a/src/wayland/autotests/client/test_error.cpp b/src/wayland/autotests/client/test_error.cpp index 2641b687dc..26ab2d590d 100644 --- a/src/wayland/autotests/client/test_error.cpp +++ b/src/wayland/autotests/client/test_error.cpp @@ -113,10 +113,11 @@ void ErrorTest::cleanup() delete m_thread; m_thread = nullptr; } - CLEANUP(m_psi) - CLEANUP(m_ci) CLEANUP(m_display) #undef CLEANUP + // these are the children of the display + m_psi = nullptr; + m_ci = nullptr; } void ErrorTest::testMultiplePlasmaShellSurfacesForSurface() diff --git a/src/wayland/autotests/client/test_fake_input.cpp b/src/wayland/autotests/client/test_fake_input.cpp index 23f9ec6bcb..6900a916ec 100644 --- a/src/wayland/autotests/client/test_fake_input.cpp +++ b/src/wayland/autotests/client/test_fake_input.cpp @@ -122,9 +122,11 @@ void FakeInputTest::cleanup() } CLEANUP(m_device) - CLEANUP(m_fakeInputInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_fakeInputInterface = nullptr; } void FakeInputTest::testAuthenticate() diff --git a/src/wayland/autotests/client/test_idle.cpp b/src/wayland/autotests/client/test_idle.cpp index cff91f8c73..ae373faac9 100644 --- a/src/wayland/autotests/client/test_idle.cpp +++ b/src/wayland/autotests/client/test_idle.cpp @@ -114,10 +114,12 @@ void IdleTest::cleanup() m_thread = nullptr; } - CLEANUP(m_idleInterface) - CLEANUP(m_seatInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_idleInterface = nullptr; + m_seatInterface = nullptr; } void IdleTest::testTimeout() diff --git a/src/wayland/autotests/client/test_plasma_window_model.cpp b/src/wayland/autotests/client/test_plasma_window_model.cpp index 22df12bb55..e8bfb8f3c0 100644 --- a/src/wayland/autotests/client/test_plasma_window_model.cpp +++ b/src/wayland/autotests/client/test_plasma_window_model.cpp @@ -145,7 +145,6 @@ void PlasmaWindowModelTest::cleanup() variable = nullptr; \ } CLEANUP(m_pw) - CLEANUP(m_plasmaVirtualDesktopManagementInterface) CLEANUP(m_queue) if (m_connection) { m_connection->deleteLater(); @@ -158,9 +157,12 @@ void PlasmaWindowModelTest::cleanup() m_thread = nullptr; } - CLEANUP(m_pwInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_plasmaVirtualDesktopManagementInterface = nullptr; + m_pwInterface = nullptr; } bool PlasmaWindowModelTest::testBooleanData(PlasmaWindowModel::AdditionalRoles role, void (PlasmaWindowInterface::*function)(bool)) diff --git a/src/wayland/autotests/client/test_pointer_constraints.cpp b/src/wayland/autotests/client/test_pointer_constraints.cpp index a11c34c193..f6bca1b462 100644 --- a/src/wayland/autotests/client/test_pointer_constraints.cpp +++ b/src/wayland/autotests/client/test_pointer_constraints.cpp @@ -142,11 +142,13 @@ void TestPointerConstraints::cleanup() m_thread = nullptr; } - CLEANUP(m_compositorInterface) - CLEANUP(m_seatInterface); - CLEANUP(m_pointerConstraintsInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_compositorInterface = nullptr; + m_seatInterface = nullptr; + m_pointerConstraintsInterface = nullptr; } void TestPointerConstraints::testLockPointer_data() diff --git a/src/wayland/autotests/client/test_selection.cpp b/src/wayland/autotests/client/test_selection.cpp index b8804018ba..347023b3e6 100644 --- a/src/wayland/autotests/client/test_selection.cpp +++ b/src/wayland/autotests/client/test_selection.cpp @@ -162,11 +162,12 @@ void SelectionTest::cleanup() delete variable; \ variable = nullptr; - CLEANUP(m_ddmInterface) - CLEANUP(m_seatInterface) - CLEANUP(m_compositorInterface) CLEANUP(m_display) #undef CLEANUP + // these are the children of the display + m_ddmInterface = nullptr; + m_seatInterface = nullptr; + m_compositorInterface = nullptr; } void SelectionTest::cleanupConnection(Connection *c) diff --git a/src/wayland/autotests/client/test_shadow.cpp b/src/wayland/autotests/client/test_shadow.cpp index 80ad7aa6b6..79b32b7af9 100644 --- a/src/wayland/autotests/client/test_shadow.cpp +++ b/src/wayland/autotests/client/test_shadow.cpp @@ -120,10 +120,12 @@ void ShadowTest::cleanup() m_thread = nullptr; } - CLEANUP(m_compositorInterface) - CLEANUP(m_shadowInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_compositorInterface = nullptr; + m_shadowInterface = nullptr; } void ShadowTest::testCreateShadow() diff --git a/src/wayland/autotests/client/test_text_input_v2.cpp b/src/wayland/autotests/client/test_text_input_v2.cpp index cec1d2125d..e58c50c1aa 100644 --- a/src/wayland/autotests/client/test_text_input_v2.cpp +++ b/src/wayland/autotests/client/test_text_input_v2.cpp @@ -153,11 +153,13 @@ void TextInputTest::cleanup() m_thread = nullptr; } - CLEANUP(m_textInputManagerV2Interface) - CLEANUP(m_compositorInterface) - CLEANUP(m_seatInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_textInputManagerV2Interface = nullptr; + m_compositorInterface = nullptr; + m_seatInterface = nullptr; } SurfaceInterface *TextInputTest::waitForSurface() diff --git a/src/wayland/autotests/client/test_wayland_blur.cpp b/src/wayland/autotests/client/test_wayland_blur.cpp index dc992c654d..6c92efc506 100644 --- a/src/wayland/autotests/client/test_wayland_blur.cpp +++ b/src/wayland/autotests/client/test_wayland_blur.cpp @@ -126,10 +126,12 @@ void TestBlur::cleanup() delete m_thread; m_thread = nullptr; } - CLEANUP(m_compositorInterface) - CLEANUP(m_blurManagerInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_compositorInterface = nullptr; + m_blurManagerInterface = nullptr; } void TestBlur::testCreate() diff --git a/src/wayland/autotests/client/test_wayland_contrast.cpp b/src/wayland/autotests/client/test_wayland_contrast.cpp index acce16e2d4..1d5b08f3fd 100644 --- a/src/wayland/autotests/client/test_wayland_contrast.cpp +++ b/src/wayland/autotests/client/test_wayland_contrast.cpp @@ -129,10 +129,12 @@ void TestContrast::cleanup() delete m_thread; m_thread = nullptr; } - CLEANUP(m_compositorInterface) - CLEANUP(m_contrastManagerInterface) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_compositorInterface = nullptr; + m_contrastManagerInterface = nullptr; } void TestContrast::testCreate() diff --git a/src/wayland/autotests/client/test_wayland_output.cpp b/src/wayland/autotests/client/test_wayland_output.cpp index dd5f3962ee..ece8c733d4 100644 --- a/src/wayland/autotests/client/test_wayland_output.cpp +++ b/src/wayland/autotests/client/test_wayland_output.cpp @@ -118,11 +118,11 @@ void TestWaylandOutput::cleanup() delete m_connection; m_connection = nullptr; - delete m_serverOutput; - m_serverOutput = nullptr; - delete m_display; m_display = nullptr; + + // these are the children of the display + m_serverOutput = nullptr; } void TestWaylandOutput::testRegistry() diff --git a/src/wayland/autotests/client/test_wayland_outputmanagement.cpp b/src/wayland/autotests/client/test_wayland_outputmanagement.cpp index 5a2f17266d..97a4da8837 100644 --- a/src/wayland/autotests/client/test_wayland_outputmanagement.cpp +++ b/src/wayland/autotests/client/test_wayland_outputmanagement.cpp @@ -200,14 +200,13 @@ void TestWaylandOutputManagement::cleanup() m_thread = nullptr; } - if (m_outputManagementInterface) { - delete m_outputManagementInterface; - m_outputManagementInterface = nullptr; - } delete m_display; m_display = nullptr; m_serverOutputs.clear(); m_clientOutputs.clear(); + + // these are the children of the display + m_outputManagementInterface = nullptr; } void TestWaylandOutputManagement::applyPendingChanges(KWaylandServer::OutputConfigurationInterface *configurationInterface) diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index 1293bb1821..7cd6e3afaa 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -236,23 +236,15 @@ void TestWaylandSeat::cleanup() m_thread = nullptr; } - delete m_compositorInterface; - m_compositorInterface = nullptr; - - delete m_seatInterface; - m_seatInterface = nullptr; - - delete m_subCompositorInterface; - m_subCompositorInterface = nullptr; - - delete m_relativePointerManagerV1Interface; - m_relativePointerManagerV1Interface = nullptr; - - delete m_pointerGesturesV1Interface; - m_pointerGesturesV1Interface = nullptr; - delete m_display; m_display = nullptr; + + // these are the children of the display + m_compositorInterface = nullptr; + m_seatInterface = nullptr; + m_subCompositorInterface = nullptr; + m_relativePointerManagerV1Interface = nullptr; + m_pointerGesturesV1Interface = nullptr; } void TestWaylandSeat::testName() diff --git a/src/wayland/autotests/client/test_wayland_surface.cpp b/src/wayland/autotests/client/test_wayland_surface.cpp index f66312ba04..225c9dfc1d 100644 --- a/src/wayland/autotests/client/test_wayland_surface.cpp +++ b/src/wayland/autotests/client/test_wayland_surface.cpp @@ -169,14 +169,12 @@ void TestWaylandSurface::cleanup() delete m_connection; m_connection = nullptr; - delete m_compositorInterface; - m_compositorInterface = nullptr; - - delete m_idleInhibitInterface; - m_idleInhibitInterface = nullptr; - delete m_display; m_display = nullptr; + + // these are the children of the display + m_compositorInterface = nullptr; + m_idleInhibitInterface = nullptr; } void TestWaylandSurface::testStaticAccessor() diff --git a/src/wayland/autotests/client/test_wayland_windowmanagement.cpp b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp index 0bdc8d7576..348d58f4c8 100644 --- a/src/wayland/autotests/client/test_wayland_windowmanagement.cpp +++ b/src/wayland/autotests/client/test_wayland_windowmanagement.cpp @@ -223,16 +223,15 @@ void TestWindowManagement::cleanup() m_connection = nullptr; m_display->dispatchEvents(); - delete m_windowManagementInterface; - m_windowManagementInterface = nullptr; - - delete m_windowInterface; - m_windowInterface = nullptr; QVERIFY(m_surfaceInterface.isNull()); delete m_display; m_display = nullptr; + + // these are the children of the display + m_windowManagementInterface = nullptr; + m_windowInterface = nullptr; } void TestWindowManagement::testUseAfterUnmap() diff --git a/src/wayland/autotests/client/test_xdg_foreign.cpp b/src/wayland/autotests/client/test_xdg_foreign.cpp index 5ac3d3f0d6..0ddc4582a2 100644 --- a/src/wayland/autotests/client/test_xdg_foreign.cpp +++ b/src/wayland/autotests/client/test_xdg_foreign.cpp @@ -159,11 +159,12 @@ void TestForeign::cleanup() delete m_thread; m_thread = nullptr; } - CLEANUP(m_foreignInterface) delete m_display; m_display = nullptr; - #undef CLEANUP + + // these are the children of the display + m_foreignInterface = nullptr; } void TestForeign::doExport() diff --git a/src/wayland/autotests/client/test_xdg_shell.cpp b/src/wayland/autotests/client/test_xdg_shell.cpp index 4a76b59a50..f3a9887af4 100644 --- a/src/wayland/autotests/client/test_xdg_shell.cpp +++ b/src/wayland/autotests/client/test_xdg_shell.cpp @@ -189,13 +189,15 @@ void XdgShellTest::cleanup() m_thread = nullptr; } - CLEANUP(m_compositorInterface) - CLEANUP(m_xdgShellInterface) - CLEANUP(m_o1Interface); - CLEANUP(m_o2Interface); - CLEANUP(m_seatInterface); CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_compositorInterface = nullptr; + m_xdgShellInterface = nullptr; + m_o1Interface = nullptr; + m_o2Interface = nullptr; + m_seatInterface = nullptr; } void XdgShellTest::testCreateSurface() diff --git a/src/wayland/autotests/server/test_datacontrol_interface.cpp b/src/wayland/autotests/server/test_datacontrol_interface.cpp index c178c6c2c6..a001d0aa6f 100644 --- a/src/wayland/autotests/server/test_datacontrol_interface.cpp +++ b/src/wayland/autotests/server/test_datacontrol_interface.cpp @@ -231,10 +231,12 @@ void DataControlInterfaceTest::cleanup() delete m_thread; m_thread = nullptr; } - CLEANUP(m_seat) - CLEANUP(m_serverCompositor) CLEANUP(m_display) #undef CLEANUP + + // these are the children of the display + m_seat = nullptr; + m_serverCompositor = nullptr; } void DataControlInterfaceTest::testCopyToControl() diff --git a/src/wayland/autotests/server/test_seat.cpp b/src/wayland/autotests/server/test_seat.cpp index 2554753148..76780a2c4b 100644 --- a/src/wayland/autotests/server/test_seat.cpp +++ b/src/wayland/autotests/server/test_seat.cpp @@ -21,7 +21,6 @@ private Q_SLOTS: void testName(); void testPointerButton(); void testPointerPos(); - void testDestroyThroughTerminate(); void testRepeatInfo(); void testMultiple(); }; @@ -155,18 +154,6 @@ void TestWaylandServerSeat::testPointerPos() QCOMPARE(seatPosSpy.last().first().toPointF(), QPointF(5, 7)); } -void TestWaylandServerSeat::testDestroyThroughTerminate() -{ - QScopedPointer display(new Display()); - display->setSocketName(s_socketName); - display->start(); - SeatInterface *seat = display->createSeat(); - QSignalSpy destroyedSpy(seat, SIGNAL(destroyed(QObject*))); - QVERIFY(destroyedSpy.isValid()); - display.reset(); - QVERIFY(!destroyedSpy.isEmpty()); -} - void TestWaylandServerSeat::testRepeatInfo() { Display display; diff --git a/src/wayland/display.cpp b/src/wayland/display.cpp index 8d98a30286..6ed9b2d363 100644 --- a/src/wayland/display.cpp +++ b/src/wayland/display.cpp @@ -116,7 +116,7 @@ Display::Display(QObject *parent) Display::~Display() { - emit aboutToTerminate(); + wl_display_destroy_clients(d->display); wl_display_destroy(d->display); } @@ -216,302 +216,219 @@ OutputInterface *Display::createOutput(QObject *parent) { OutputInterface *output = new OutputInterface(this, parent); connect(output, &QObject::destroyed, this, [this,output] { d->outputs.removeAll(output); }); - connect(this, &Display::aboutToTerminate, output, [this,output] { removeOutput(output); }); d->outputs << output; return output; } CompositorInterface *Display::createCompositor(QObject *parent) { - CompositorInterface *compositor = new CompositorInterface(this, parent); - connect(this, &Display::aboutToTerminate, compositor, [compositor] { delete compositor; }); - return compositor; + return new CompositorInterface(this, parent); } OutputDeviceInterface *Display::createOutputDevice(QObject *parent) { OutputDeviceInterface *output = new OutputDeviceInterface(this, parent); connect(output, &QObject::destroyed, this, [this,output] { d->outputdevices.removeAll(output); }); - connect(this, &Display::aboutToTerminate, output, [this,output] { removeOutputDevice(output); }); d->outputdevices << output; return output; } OutputManagementInterface *Display::createOutputManagement(QObject *parent) { - OutputManagementInterface *om = new OutputManagementInterface(this, parent); - connect(this, &Display::aboutToTerminate, om, [om] { delete om; }); - return om; + return new OutputManagementInterface(this, parent); } SeatInterface *Display::createSeat(QObject *parent) { SeatInterface *seat = new SeatInterface(this, parent); connect(seat, &QObject::destroyed, this, [this, seat] { d->seats.removeAll(seat); }); - connect(this, &Display::aboutToTerminate, seat, [seat] { delete seat; }); d->seats << seat; return seat; } SubCompositorInterface *Display::createSubCompositor(QObject *parent) { - auto c = new SubCompositorInterface(this, parent); - connect(this, &Display::aboutToTerminate, c, [c] { delete c; }); - return c; + return new SubCompositorInterface(this, parent); } DataDeviceManagerInterface *Display::createDataDeviceManager(QObject *parent) { - auto m = new DataDeviceManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, m, [m] { delete m; }); - return m; + return new DataDeviceManagerInterface(this, parent); } PlasmaShellInterface *Display::createPlasmaShell(QObject* parent) { - auto s = new PlasmaShellInterface(this, parent); - connect(this, &Display::aboutToTerminate, s, [s] { delete s; }); - return s; + return new PlasmaShellInterface(this, parent); } PlasmaWindowManagementInterface *Display::createPlasmaWindowManagement(QObject *parent) { - auto wm = new PlasmaWindowManagementInterface(this, parent); - connect(this, &Display::aboutToTerminate, wm, [wm] { delete wm; }); - return wm; + return new PlasmaWindowManagementInterface(this, parent); } IdleInterface *Display::createIdle(QObject *parent) { - auto i = new IdleInterface(this, parent); - connect(this, &Display::aboutToTerminate, i, [i] { delete i; }); - return i; + return new IdleInterface(this, parent); } FakeInputInterface *Display::createFakeInput(QObject *parent) { - auto i = new FakeInputInterface(this, parent); - connect(this, &Display::aboutToTerminate, i, [i] { delete i; }); - return i; + return new FakeInputInterface(this, parent); } ShadowManagerInterface *Display::createShadowManager(QObject *parent) { - auto s = new ShadowManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, s, [s] { delete s; }); - return s; + return new ShadowManagerInterface(this, parent); } BlurManagerInterface *Display::createBlurManager(QObject *parent) { - auto b = new BlurManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new BlurManagerInterface(this, parent); } ContrastManagerInterface *Display::createContrastManager(QObject *parent) { - auto b = new ContrastManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new ContrastManagerInterface(this, parent); } SlideManagerInterface *Display::createSlideManager(QObject *parent) { - auto b = new SlideManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new SlideManagerInterface(this, parent); } DpmsManagerInterface *Display::createDpmsManager(QObject *parent) { - auto d = new DpmsManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new DpmsManagerInterface(this, parent); } ServerSideDecorationManagerInterface *Display::createServerSideDecorationManager(QObject *parent) { - auto d = new ServerSideDecorationManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new ServerSideDecorationManagerInterface(this, parent); } ScreencastV1Interface *Display::createScreencastV1Interface(QObject *parent) { - auto s = new ScreencastV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, s, [s] { delete s; }); - return s; + return new ScreencastV1Interface(this, parent); } TextInputManagerV2Interface *Display::createTextInputManagerV2(QObject *parent) { - auto t = new TextInputManagerV2Interface(this, parent); - connect(this, &Display::aboutToTerminate, t, [t] { delete t; }); - return t; + return new TextInputManagerV2Interface(this, parent); } TextInputManagerV3Interface *Display::createTextInputManagerV3(QObject *parent) { - auto t = new TextInputManagerV3Interface(this, parent); - connect(this, &Display::aboutToTerminate, t, [t] { delete t; }); - return t; + return new TextInputManagerV3Interface(this, parent); } - XdgShellInterface *Display::createXdgShell(QObject *parent) { - XdgShellInterface *shell = new XdgShellInterface(this, parent); - connect(this, &Display::aboutToTerminate, shell, [shell] { delete shell; }); - return shell; + return new XdgShellInterface(this, parent); } RelativePointerManagerV1Interface *Display::createRelativePointerManagerV1(QObject *parent) { - RelativePointerManagerV1Interface *r = new RelativePointerManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, r, [r] { delete r; }); - return r; + return new RelativePointerManagerV1Interface(this, parent); } PointerGesturesV1Interface *Display::createPointerGesturesV1(QObject *parent) { - PointerGesturesV1Interface *p = new PointerGesturesV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, p, [p] { delete p; }); - return p; + return new PointerGesturesV1Interface(this, parent); } PointerConstraintsV1Interface *Display::createPointerConstraintsV1(QObject *parent) { - PointerConstraintsV1Interface *p = new PointerConstraintsV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, p, [p] { delete p; }); - return p; + return new PointerConstraintsV1Interface(this, parent); } XdgForeignV2Interface *Display::createXdgForeignV2Interface(QObject *parent) { - XdgForeignV2Interface *foreign = new XdgForeignV2Interface(this, parent); - connect(this, &Display::aboutToTerminate, foreign, [foreign] { delete foreign; }); - return foreign; + return new XdgForeignV2Interface(this, parent); } IdleInhibitManagerV1Interface *Display::createIdleInhibitManagerV1(QObject *parent) { - IdleInhibitManagerV1Interface *idleManager = new IdleInhibitManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, idleManager, [idleManager] { delete idleManager; }); - return idleManager; + return new IdleInhibitManagerV1Interface(this, parent); } AppMenuManagerInterface *Display::createAppMenuManagerInterface(QObject *parent) { - auto b = new AppMenuManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new AppMenuManagerInterface(this, parent); } ServerSideDecorationPaletteManagerInterface *Display::createServerSideDecorationPaletteManager(QObject *parent) { - auto b = new ServerSideDecorationPaletteManagerInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new ServerSideDecorationPaletteManagerInterface(this, parent); } LinuxDmabufUnstableV1Interface *Display::createLinuxDmabufInterface(QObject *parent) { - auto b = new LinuxDmabufUnstableV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new LinuxDmabufUnstableV1Interface(this, parent); } PlasmaVirtualDesktopManagementInterface *Display::createPlasmaVirtualDesktopManagement(QObject *parent) { - auto b = new PlasmaVirtualDesktopManagementInterface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new PlasmaVirtualDesktopManagementInterface(this, parent); } XdgOutputManagerV1Interface *Display::createXdgOutputManagerV1(QObject *parent) { - auto b = new XdgOutputManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, b, [b] { delete b; }); - return b; + return new XdgOutputManagerV1Interface(this, parent); } XdgDecorationManagerV1Interface *Display::createXdgDecorationManagerV1(QObject *parent) { - auto d = new XdgDecorationManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new XdgDecorationManagerV1Interface(this, parent); } EglStreamControllerInterface *Display::createEglStreamControllerInterface(QObject *parent) { - EglStreamControllerInterface *e = new EglStreamControllerInterface(this, parent); - connect(this, &Display::aboutToTerminate, e, [e] { delete e; }); - return e; + return new EglStreamControllerInterface(this, parent); } KeyStateInterface *Display::createKeyStateInterface(QObject *parent) { - auto d = new KeyStateInterface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new KeyStateInterface(this, parent); } TabletManagerV2Interface *Display::createTabletManagerV2(QObject *parent) { - auto d = new TabletManagerV2Interface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new TabletManagerV2Interface(this, parent); } DataControlDeviceManagerV1Interface *Display::createDataControlDeviceManagerV1(QObject *parent) { - auto m = new DataControlDeviceManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, m, [m] { delete m; }); - return m; + return new DataControlDeviceManagerV1Interface(this, parent); } KeyboardShortcutsInhibitManagerV1Interface *Display::createKeyboardShortcutsInhibitManagerV1(QObject *parent) { - auto d = new KeyboardShortcutsInhibitManagerV1Interface(this, parent); - - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new KeyboardShortcutsInhibitManagerV1Interface(this, parent); } InputMethodV1Interface *Display::createInputMethodInterface(QObject *parent) { - auto d = new InputMethodV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, d, [d] { delete d; }); - return d; + return new InputMethodV1Interface(this, parent); } ViewporterInterface *Display::createViewporter(QObject *parent) { - auto viewporter = new ViewporterInterface(this, parent); - connect(this, &Display::aboutToTerminate, viewporter, [viewporter] { delete viewporter; }); - return viewporter; + return new ViewporterInterface(this, parent); } PrimarySelectionDeviceManagerV1Interface *Display::createPrimarySelectionDeviceManagerV1(QObject *parent) { - auto primarySelection = new PrimarySelectionDeviceManagerV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, primarySelection, [primarySelection] { delete primarySelection; }); - return primarySelection; + return new PrimarySelectionDeviceManagerV1Interface(this, parent); } InputPanelV1Interface *Display::createInputPanelInterface(QObject *parent) { - auto p = new InputPanelV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, p, [p] { delete p; }); - return p; + return new InputPanelV1Interface(this, parent); } LayerShellV1Interface *Display::createLayerShellV1(QObject *parent) { - auto shell = new LayerShellV1Interface(this, parent); - connect(this, &Display::aboutToTerminate, shell, [shell] { delete shell; }); - return shell; + return new LayerShellV1Interface(this, parent); } void Display::createShm() diff --git a/src/wayland/display.h b/src/wayland/display.h index fb20fcbbd7..5284950555 100644 --- a/src/wayland/display.h +++ b/src/wayland/display.h @@ -378,7 +378,6 @@ Q_SIGNALS: void socketNameChanged(const QString&); void automaticSocketNamingChanged(bool); void runningChanged(bool); - void aboutToTerminate(); void clientConnected(KWaylandServer::ClientConnection*); void clientDisconnected(KWaylandServer::ClientConnection*); diff --git a/src/wayland/server/global.cpp b/src/wayland/server/global.cpp index df723d182a..86ff275af5 100644 --- a/src/wayland/server/global.cpp +++ b/src/wayland/server/global.cpp @@ -33,15 +33,28 @@ void Global::Private::create() global = wl_global_create(*display, m_interface, m_version, this, bind); } +static void handleDisplayDestroyed(struct wl_listener *listener, void *data) +{ + Q_UNUSED(data) + Global *global = static_cast(listener)->global; + global->destroy(); +} + Global::Global(Global::Private *d, QObject *parent) : QObject(parent) , d(d) { + d->displayDestroyListener.notify = handleDisplayDestroyed; + d->displayDestroyListener.global = this; + d->displayDestroyListener.link.next = nullptr; + d->displayDestroyListener.link.prev = nullptr; + wl_display_add_destroy_listener(*d->display, &d->displayDestroyListener); } Global::~Global() { destroy(); + wl_list_remove(&d->displayDestroyListener.link); } void Global::create() diff --git a/src/wayland/server/global_p.h b/src/wayland/server/global_p.h index 19a02e16ee..15e8e4c0d8 100644 --- a/src/wayland/server/global_p.h +++ b/src/wayland/server/global_p.h @@ -8,12 +8,16 @@ #include "global.h" -struct wl_client; -struct wl_interface; +#include namespace KWaylandServer { +struct DisplayDestroyListener : public wl_listener +{ + Global *global = nullptr; +}; + class Global::Private { public: @@ -23,6 +27,7 @@ public: Display *display = nullptr; wl_global *global = nullptr; + DisplayDestroyListener displayDestroyListener; protected: Private(Display *d, const wl_interface *interface, quint32 version);