From 6ca5afd91dca3ad3626fbfd1b48c0737280ca5e5 Mon Sep 17 00:00:00 2001 From: zhaofangxun Date: Thu, 8 Oct 2026 15:14:12 +0800 Subject: [PATCH] fix: prevent X11 IO error crash on mode switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- shell/CMakeLists.txt | 2 ++ shell/main.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt index 8f6adb1c9..9770c64a9 100644 --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -6,6 +6,7 @@ find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED) 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) find_package(PkgConfig REQUIRED) @@ -48,6 +49,7 @@ target_link_libraries(dde-shell PRIVATE Dtk${DTK_VERSION_MAJOR}::Widget Qt${QT_VERSION_MAJOR}::DBus PkgConfig::WaylandClient + PkgConfig::X11 ) configure_file(${CMAKE_SOURCE_DIR}/misc/dde-shell-plugin@.service.in diff --git a/shell/main.cpp b/shell/main.cpp index aa7335652..77c13edf5 100644 --- a/shell/main.cpp +++ b/shell/main.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include "applet.h" #include "containment.h" @@ -134,6 +136,11 @@ class AppletManager QList m_loaders; }; +static int x11IOErrorHandler(Display *) +{ + _exit(0); +} + int main(int argc, char *argv[]) { setenv("DSG_APP_ID", "org.deepin.dde.shell", 0); @@ -255,6 +262,8 @@ int main(int argc, char *argv[]) manager.exec(); }, Qt::QueuedConnection); + XSetIOErrorHandler(x11IOErrorHandler); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, qApp, [&manager]() { qCInfo(dsLog) << "Exit dde-shell."; DPluginLoader::instance()->destroy();