From 5307e3c81b28e129ff47991c69f72990c51697ce Mon Sep 17 00:00:00 2001 From: zhangkun Date: Sat, 21 Mar 2026 15:14:29 +0800 Subject: [PATCH] fix: add X connection monitoring for session logout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added XCB dependency and implemented X server connection monitoring to detect when the X server disconnects. This ensures the session properly logs out when the X server connection is lost, preventing orphaned sessions. 1. Added libxcb1-dev to Build-Depends in debian/control 2. Added XCB pkg-config check and linking in CMakeLists.txt 3. Implemented watchXConnection() method that establishes an XCB connection and monitors the file descriptor using QSocketNotifier 4. When X connection errors are detected, the session automatically triggers logout to clean up resources 5. Only activates on X11 displays, not Wayland This fix addresses cases where X server crashes or disconnects unexpectedly, leaving the session manager running without a display server. fix: 添加X连接监控以实现会话登出 添加XCB依赖并实现X服务器连接监控,以检测X服务器断开连接的情况。这确保当X 服务器连接丢失时会话能正确登出,防止出现孤儿会话。 1. 在debian/control的Build-Depends中添加libxcb1-dev 2. 在CMakeLists.txt中添加XCB pkg-config检查和链接 3. 实现watchXConnection()方法,使用XCB建立连接并通过QSocketNotifier监控 文件描述符 4. 当检测到X连接错误时,会话自动触发登出以清理资源 5. 仅在X11显示环境下激活,Wayland环境下不启用 此修复解决了X服务器崩溃或意外断开连接时,会话管理器在没有显示服务器的情 况下继续运行的问题。 PMS: BUG-353461 --- debian/control | 1 + src/dde-session/CMakeLists.txt | 4 ++- src/dde-session/impl/sessionmanager.cpp | 33 +++++++++++++++++++++++++ src/dde-session/impl/sessionmanager.h | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 7a4fc96..ff9279d 100644 --- a/debian/control +++ b/debian/control @@ -16,6 +16,7 @@ Build-Depends: libxfixes-dev, pkg-config, qt6-base-dev, + libxcb1-dev, Standards-Version: 4.1.3 Homepage: https://www.deepin.org diff --git a/src/dde-session/CMakeLists.txt b/src/dde-session/CMakeLists.txt index 832cc9d..249b2a0 100644 --- a/src/dde-session/CMakeLists.txt +++ b/src/dde-session/CMakeLists.txt @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. +# SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. # # SPDX-License-Identifier: CC0-1.0 @@ -14,6 +14,7 @@ pkg_check_modules(GIO2 REQUIRED IMPORTED_TARGET gio-2.0) pkg_check_modules(XCURSOR REQUIRED IMPORTED_TARGET xcursor) pkg_check_modules(XFIXES REQUIRED IMPORTED_TARGET xfixes) pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11) +pkg_check_modules(XCB REQUIRED IMPORTED_TARGET xcb) # dbus adaptor qt_add_dbus_adaptor(ADAPTER_SOURCES @@ -91,6 +92,7 @@ target_link_libraries(dde-session PkgConfig::XCURSOR PkgConfig::XFIXES PkgConfig::X11 + PkgConfig::XCB ) target_include_directories(dde-session PUBLIC diff --git a/src/dde-session/impl/sessionmanager.cpp b/src/dde-session/impl/sessionmanager.cpp index 7a27f6c..9b50d3e 100644 --- a/src/dde-session/impl/sessionmanager.cpp +++ b/src/dde-session/impl/sessionmanager.cpp @@ -18,9 +18,11 @@ #include #include #include +#include #include #include +#include #define MASK_SERVICE(service) \ {\ @@ -541,9 +543,40 @@ void SessionManager::init() startAtSpiService(); startObexService(); + if (!Utils::IS_WAYLAND_DISPLAY) { + watchXConnection(); + } + qInfo() << "session manager init finished"; } +void SessionManager::watchXConnection() +{ + xcb_connection_t *conn = xcb_connect(nullptr, nullptr); + if (xcb_connection_has_error(conn)) { + qWarning() << "watchXConnection: failed to connect to X server"; + xcb_disconnect(conn); + return; + } + + int fd = xcb_get_file_descriptor(conn); + auto *notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, [=]() { + // 排空所有待处理事件 + xcb_generic_event_t *ev; + while ((ev = xcb_poll_for_event(conn)) != nullptr) { + free(ev); + } + // 若连接已断开则触发登出 + if (xcb_connection_has_error(conn)) { + qWarning() << "X connection closed, logging out"; + notifier->setEnabled(false); + xcb_disconnect(conn); + doLogout(); + } + }); +} + void SessionManager::stopSogouIme() { // TODO 使用kill函数杀死进程,前提是进程存在 diff --git a/src/dde-session/impl/sessionmanager.h b/src/dde-session/impl/sessionmanager.h index 5d5b867..5b2e12e 100644 --- a/src/dde-session/impl/sessionmanager.h +++ b/src/dde-session/impl/sessionmanager.h @@ -100,6 +100,7 @@ public Q_SLOTS: void setDPMSMode(bool on); void handleOSSignal(); + void watchXConnection(); void shutdown(bool force); void reboot(bool force);