From 9e7b1b0e9850d6ff19cd26ffb9f3ac72aed140f4 Mon Sep 17 00:00:00 2001 From: zhaoyingzhen Date: Tue, 9 Jun 2026 19:48:24 +0800 Subject: [PATCH] fix: avoid xdg_activation_v1 destroy on a torn-down display at exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XdgActivationV1 was a function-local static (Meyers singleton). Its destructor runs at __cxa_finalize, after main() returns and ~QGuiApplication has already torn down the Wayland connection, so xdg_activation_v1::destroy() marshals a request onto an already-freed wl_proxy/wl_display and crashes (SIGSEGV in wl_map_insert_at). It is triggered on normal process exit, e.g. when the session exits during a VT/TTY switch. Make instance() heap-allocate the object and parent it to qApp (held via a non-owning QPointer) so it is destroyed within the Qt shutdown sequence rather than at static-destruction time. Also guard the destructor with qApp, since QCoreApplication::self is already null when qApp deletes its children, ensuring destroy() is never marshalled onto a dead wl_display. XdgActivationV1 原本是函数局部静态量(Meyers 单例),其析构发生在 __cxa_finalize, 即 main() 返回、~QGuiApplication 已销毁 Wayland 连接之后。此时调用 xdg_activation_v1::destroy() 会向已释放的 wl_proxy/wl_display 发送请求而崩溃 (SIGSEGV in wl_map_insert_at),在进程正常退出时触发,例如切换 VT/TTY 导致会话退出。 改为在 instance() 中堆分配对象并挂到 qApp(用非持有的 QPointer 持有),使其在 Qt 关闭流程中销毁,而非静态析构期;析构函数再加 qApp 守卫:qApp 删除子对象时 QCoreApplication::self 已为空,确保绝不会再向已销毁的 wl_display 发送 destroy()。 Log: avoid xdg_activation_v1 destroy on a torn-down display at exit Pms: BUG-346387 Change-Id: Ibd924692759de957b18b78ccb1fcb0968d4aa030 --- src/ddeintegration/xdgactivation.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/ddeintegration/xdgactivation.cpp b/src/ddeintegration/xdgactivation.cpp index 25365330..0641b062 100644 --- a/src/ddeintegration/xdgactivation.cpp +++ b/src/ddeintegration/xdgactivation.cpp @@ -4,7 +4,9 @@ #include "xdgactivation.h" +#include #include +#include #include #include #include @@ -37,8 +39,16 @@ void XdgActivationTokenV1::xdg_activation_token_v1_done(const QString &token) XdgActivationV1 *XdgActivationV1::instance() { - static XdgActivationV1 s_instance; - return &s_instance; + // Not a function-local static: a static is destroyed at process exit, after + // ~QGuiApplication has dropped the Wayland connection, so destroy() in the + // destructor would marshal onto a freed wl_proxy and crash. Parent to qApp so + // it's torn down with the Qt object tree instead. + static QPointer s_instance; + if (!s_instance) { + s_instance = new XdgActivationV1; + s_instance->setParent(qApp); + } + return s_instance; } XdgActivationV1::XdgActivationV1() @@ -48,7 +58,9 @@ XdgActivationV1::XdgActivationV1() XdgActivationV1::~XdgActivationV1() { - if (isInitialized()) + // Runs only at shutdown, when qApp and the Wayland connection may already be + // gone; guard so we never send destroy() onto a dead wl_display. + if (qApp && isInitialized()) destroy(); }