Skip to content

fix: prevent X11 IO error crash on mode switch - #1755

Open
MyLeeJiEun wants to merge 1 commit into
linuxdeepin:masterfrom
MyLeeJiEun:agent/pms-bug-bot/9fc5cb1a33d9
Open

MyLeeJiEun wants to merge 1 commit into
linuxdeepin:masterfrom
MyLeeJiEun:agent/pms-bug-bot/9fc5cb1a33d9

Conversation

@MyLeeJiEun

@MyLeeJiEun MyLeeJiEun commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Root Cause Analysis

When switching from terminal mode (sudo init 3) back to graphical mode (sudo init 5), the X11 server shuts down during init 3. Processes still holding X11 display connections (dde-shell) encounter an X11 IO error. Since dde-shell does not install a custom X11 IO error handler, libX11's default _XDefaultIOError calls exit(1), which triggers C++ static destructors (e.g., QWindow::~QWindow() → QSurface::~QSurface() → QOpenGLContext::currentContext()) that access the dead X11 connection, causing SIGSEGV.

Key evidence:

  • GDB backtrace shows crash in exit() called from _XDefaultIOError → _XIOError
  • dde-shell/shell/main.cpp never calls XSetIOErrorHandler() before entering the event loop

Fix

Install a custom X11 IO error handler x11IOErrorHandler that calls _exit(0) to bypass the C++ destructor chain, and register it via XSetIOErrorHandler() before the event loop starts. Also add X11 link dependency (pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)) in CMakeLists.txt.

Change Safety Assessment

Code Safety

  • Risk Level: Low
  • Only new code added (include, static function, one function call, CMake link dependency); no existing function signatures or logic modified
  • No external callers affected; the handler only triggers on X11 connection loss

Business Impact Scope

Affects the dde-shell desktop process exit path when the X11 connection is lost. Normal desktop panel display and interaction are unaffected. The fix ensures clean process termination without SIGSEGV during display server transitions.

Verification Suggestion

Test sudo init 3 → sudo init 5 switching and verify no coredump for dde-shell. Verify normal desktop panel display and interaction work after mode switch.


根因分析

从终端模式(sudo init 3)切换回图形化模式(sudo init 5)时,init 3 期间 X11 服务器关闭。仍持有 X11 显示连接的进程(dde-shell)遭遇 X11 IO 错误。由于 dde-shell 未安装自定义 X11 IO 错误处理器,libX11 默认处理器 _XDefaultIOError 调用 exit(1),触发 C++ 静态析构函数(如 QWindow::~QWindow() → QSurface::~QSurface() → QOpenGLContext::currentContext())访问已失效的 X11 连接,导致 SIGSEGV。

关键证据:

  • GDB backtrace 显示崩溃发生在 exit() 中,由 _XDefaultIOError → _XIOError 调用
  • dde-shell/shell/main.cpp 在进入事件循环前从未调用 XSetIOErrorHandler()

修复方案

安装自定义 X11 IO 错误处理器 x11IOErrorHandler,调用 _exit(0) 绕过 C++ 析构链,在事件循环开始前通过 XSetIOErrorHandler() 注册。同时在 CMakeLists.txt 中添加 X11 链接依赖(pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11))。

改动安全评估

代码安全

  • 风险等级:低
  • 仅新增代码(include、静态函数、一个函数调用、CMake 链接依赖),未修改任何已有函数签名或逻辑
  • 无外部调用者受影响;处理器仅在 X11 连接断开时触发

业务影响范围

影响 dde-shell 桌面进程在 X11 连接断开时的退出路径。正常桌面面板显示和交互不受影响。修复确保在显示服务器切换期间进程干净退出,不产生 SIGSEGV。

验证建议

测试 sudo init 3 → sudo init 5 切换,验证 dde-shell 无 coredump。验证模式切换后桌面面板正常显示和交互。

PMS: BUG-378799

Summary by Sourcery

Handle X11 connection loss with immediate process termination to avoid destructor-related crashes during terminal-to-graphical mode switches.

Bug Fixes:

  • Prevent dde-shell from crashing with SIGSEGV when its X11 connection is lost during display mode transitions.

Build:

  • Add the X11 package as a required dependency and link it to dde-shell.

1. Root cause: dde-shell does not install a custom X11 IO error
   handler, libX11 default _XDefaultIOError calls exit(1) on X
   connection death, triggering C++ static destructors that access
   the dead X11 connection, causing SIGSEGV
2. Fix: install custom x11IOErrorHandler calling _exit(0) to bypass
   C++ destructor chain, add X11 link dependency in CMakeLists.txt
3. Impact: only affects process exit path when X11 connection is
   lost, no behavior change for normal operation

Log: fix crash when switching from terminal mode to graphical mode

Influence:
1. Test switching from init 3 to init 5, verify no coredump
2. Verify normal desktop panel display and interaction
3. Verify no regression on existing dde-shell functionality

fix: 修复终端模式切换到图形化时的崩溃问题

1. 根因:dde-shell 未安装自定义 X11 IO 错误处理器,libX11 默认的
   _XDefaultIOError 在 X 连接断开时调用 exit(1),触发 C++ 静态
   析构函数访问已断开的 X11 连接,导致 SIGSEGV
2. 方案:安装自定义 x11IOErrorHandler 调用 _exit(0) 绕过 C++ 析构
   链,并在 CMakeLists.txt 中添加 X11 链接依赖
3. 影响:仅影响 X11 连接断开时的进程退出路径,正常运行无行为变化

Log: 修复终端模式切换到图形化时的崩溃问题

Influence:
1. 测试 init 3 切换到 init 5 后 dde-shell 无 coredump
2. 验证桌面面板正常显示和交互
3. 验证现有 dde-shell 功能无回归

PMS: BUG-378799
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: MyLeeJiEun

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

@sourcery-ai

sourcery-ai Bot commented Oct 8, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

The PR prevents dde-shell from crashing when the X11 server disappears during terminal/graphical mode transitions by registering an Xlib I/O error handler that bypasses unsafe C++ destructors with immediate process termination, and adds the corresponding X11 build dependency. Review the handler’s registration timing and the intentional loss of graceful cleanup on X11 disconnect, then verify init 3/init 5 switching and normal desktop behavior.

Sequence diagram for safe dde-shell termination on X11 disconnect

sequenceDiagram
    participant X11 as X11Server
    participant Shell as dde_shell
    participant Xlib as libX11
    participant Handler as x11IOErrorHandler
    participant OS as Process

    Shell->>Xlib: XSetIOErrorHandler(x11IOErrorHandler)
    Shell->>X11: Maintain display connection
    X11-->>Xlib: Connection lost during mode switch
    Xlib->>Handler: x11IOErrorHandler(Display *)
    Handler->>OS: _exit(0)
    OS-->>Shell: Terminate immediately without C++ destructors
Loading

File-Level Changes

Change Details Files
Prevent SIGSEGV during X11 connection loss by terminating immediately instead of running C++ cleanup after libX11 reports an I/O error.
  • Add a process-level X11 I/O error callback that invokes _exit(0).
  • Register the callback before the Qt event loop processes events.
shell/main.cpp
Declare and link the shell target against X11 for the new Xlib API usage.
  • Require the x11 pkg-config module.
  • Add the imported X11 target to dde-shell link dependencies.
shell/CMakeLists.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

Hi @MyLeeJiEun. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@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.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="shell/CMakeLists.txt" line_range="9" />
<code_context>
 find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Widgets Gui WaylandClient)
 find_package(TreelandProtocols REQUIRED)
 pkg_check_modules(WaylandClient REQUIRED IMPORTED_TARGET wayland-client)
+pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)

 if (NOT DEFINED SYSTEMD_USER_UNIT_DIR)
</code_context>
<issue_to_address>
**Wayland-only builds still require X11**

When `BUILD_WITH_X11` is disabled and X11 development files are unavailable, the unconditional `pkg_check_modules(X11 REQUIRED ...)` lookup fails during CMake configuration, and the unconditional Xlib include in `main.cpp` also prevents a build without X11. The Wayland-only build cannot complete.

Gate the X11 pkg-config lookup and Xlib include on `BUILD_WITH_X11`.

Also at `shell/main.cpp:19-20`, `shell/main.cpp:265`, `shell/CMakeLists.txt:52`.
</issue_to_address>

### Comment 2
<location path="shell/main.cpp" line_range="265" />
<code_context>
         manager.exec();
     }, Qt::QueuedConnection);

+    XSetIOErrorHandler(x11IOErrorHandler);
+
     QObject::connect(qApp, &QCoreApplication::aboutToQuit, qApp, [&manager]() {
</code_context>
<issue_to_address>
**Startup X11 errors still trigger destructor crashes**

When the X server connection fails during application or shell startup, before `XSetIOErrorHandler` is called, the default libX11 handler remains active while the application and applet setup run; it calls `exit()` on an I/O error, running destructors against the dead display and potentially crashing dde-shell.

Install the I/O error handler before any startup code can use the X11 connection.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread shell/CMakeLists.txt
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Widgets Gui WaylandClient)
find_package(TreelandProtocols REQUIRED)
pkg_check_modules(WaylandClient REQUIRED IMPORTED_TARGET wayland-client)
pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Wayland-only builds still require X11

When BUILD_WITH_X11 is disabled and X11 development files are unavailable, the unconditional pkg_check_modules(X11 REQUIRED ...) lookup fails during CMake configuration, and the unconditional Xlib include in main.cpp also prevents a build without X11. The Wayland-only build cannot complete.

Gate the X11 pkg-config lookup and Xlib include on BUILD_WITH_X11.

Also at shell/main.cpp:19-20, shell/main.cpp:265, shell/CMakeLists.txt:52.

Prompt for AI agents
In `shell/CMakeLists.txt` at line 9:

**Wayland-only builds still require X11**

When `BUILD_WITH_X11` is disabled and X11 development files are unavailable, the unconditional `pkg_check_modules(X11 REQUIRED ...)` lookup fails during CMake configuration, and the unconditional Xlib include in `main.cpp` also prevents a build without X11. The Wayland-only build cannot complete.

Gate the X11 pkg-config lookup and Xlib include on `BUILD_WITH_X11`.

Also at `shell/main.cpp:19-20`, `shell/main.cpp:265`, `shell/CMakeLists.txt:52`.

Comment thread shell/main.cpp
manager.exec();
}, Qt::QueuedConnection);

XSetIOErrorHandler(x11IOErrorHandler);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium · Startup X11 errors still trigger destructor crashes

When the X server connection fails during application or shell startup, before XSetIOErrorHandler is called, the default libX11 handler remains active while the application and applet setup run; it calls exit() on an I/O error, running destructors against the dead display and potentially crashing dde-shell.

Install the I/O error handler before any startup code can use the X11 connection.

Prompt for AI agents
In `shell/main.cpp` at line 265:

**Startup X11 errors still trigger destructor crashes**

When the X server connection fails during application or shell startup, before `XSetIOErrorHandler` is called, the default libX11 handler remains active while the application and applet setup run; it calls `exit()` on an I/O error, running destructors against the dead display and potentially crashing dde-shell.

Install the I/O error handler before any startup code can use the X11 connection.

@deepin-bot

deepin-bot Bot commented Oct 12, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.57
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1758

@deepin-bot

deepin-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.58
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1765

@deepin-bot

deepin-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.59
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1766

@deepin-bot

deepin-bot Bot commented Oct 20, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.60
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1773

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants