Skip to content

fix: avoid xdg_activation_v1 destroy on a torn-down display at exit#771

Merged
yixinshark merged 1 commit into
linuxdeepin:masterfrom
yixinshark:fix-xdgactivation-exit-crash
Jun 9, 2026
Merged

fix: avoid xdg_activation_v1 destroy on a torn-down display at exit#771
yixinshark merged 1 commit into
linuxdeepin:masterfrom
yixinshark:fix-xdgactivation-exit-crash

Conversation

@yixinshark

Copy link
Copy Markdown
Contributor

Summary

  • DDEIntegration::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).
  • Triggered on normal process exit, notably when the session exits during a VT/TTY switch.
  • Fix: instance() now heap-allocates the object and parents it to qApp (held via a non-owning QPointer) so it is destroyed within Qt's shutdown sequence, not at static-destruction time. The destructor is additionally guarded with qApp (which is already null when qApp deletes its children), so destroy() is never marshalled onto a dead wl_display.

Crash backtrace (before fix)

#0 wl_map_insert_at (data=0x0)
#1 proxy_destroy
#3 wl_proxy_marshal_array_flags
#4 wl_proxy_marshal_flags
#5 QtWayland::xdg_activation_v1::destroy()
#6 DDEIntegration::XdgActivationV1::~XdgActivationV1   (launchpadcommon.so, src/ddeintegration/xdgactivation.cpp)
#7 __cxa_finalize / exit

Test plan

  • Run on a treeland/Wayland session; trigger an app-launch activation so the singleton is initialized.
  • Switch VT to a text console and back (or otherwise cause the desktop dde-shell process to exit); verify no dde-shell coredump in coredumpctl with the xdg_activation_v1::destroy frame.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @yixinshark, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

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
@yixinshark yixinshark force-pushed the fix-xdgactivation-exit-crash branch from a3604b1 to 9e7b1b0 Compare June 9, 2026 12:00
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

这段代码是对XdgActivationV1类的改进,主要关注了单例模式的生命周期管理和Qt应用程序退出时的安全性。以下是我的审查意见:

语法逻辑

  1. 语法正确,逻辑清晰。代码使用了QPointer来管理单例实例,这是一个很好的实践,可以避免在Qt对象被删除后访问无效指针。
  2. 单例模式的实现方式更加安全,通过将单例对象设置为QCoreApplication的子对象,确保其与Qt应用程序的生命周期保持一致。

代码质量

  1. 代码质量有明显提升。原来的静态变量在程序退出时可能引发问题,因为Qt的事件循环和Wayland连接可能已经销毁。
  2. 添加了必要的注释,解释了为什么使用QPointer而不是普通的静态指针,以及为什么在析构函数中检查qApp的存在性。

代码性能

  1. 性能方面没有明显问题。QPointer的开销很小,主要是增加了额外的指针检查。
  2. 单例的懒加载模式(第一次使用时创建)是合理的,避免了不必要的资源占用。

代码安全

  1. 安全性显著提高。原来的实现可能在Qt应用程序退出后访问已销毁的Wayland资源,导致崩溃。
  2. 通过检查qApp的存在性,确保在Qt应用程序已经销毁的情况下不会尝试销毁Wayland资源。
  3. 使用QPointer而不是原始指针,可以防止在对象被删除后访问无效指针。

改进建议

  1. 可以考虑在XdgActivationV1类中添加一个标志位,标记单例是否已经被销毁,以防止在极端情况下重复创建或访问已销毁的实例。
  2. 可以考虑使用Qt的Q_DISABLE_COPY宏来禁用拷贝构造和赋值操作,确保单例的唯一性。
  3. 在XdgActivationV1的构造函数中,可以添加更多的错误检查,确保在初始化失败时能够正确处理。

总体而言,这次改进很好地解决了原代码中可能存在的生命周期管理问题,提高了代码的健壮性和安全性。

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, yixinshark

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@yixinshark yixinshark merged commit 9332e2b into linuxdeepin:master Jun 9, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants