Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions shell/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

find_package(Dtk${DTK_VERSION_MAJOR} COMPONENTS Widget REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Widgets Gui WaylandClient)
pkg_check_modules(X11 REQUIRED IMPORTED_TARGET x11)
find_package(TreelandProtocols REQUIRED)
pkg_check_modules(WaylandClient REQUIRED IMPORTED_TARGET wayland-client)

Expand Down Expand Up @@ -46,6 +47,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
Expand Down
38 changes: 38 additions & 0 deletions shell/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@
#include <QQuickWindow>
#include <QWindow>

#include <csignal>

Check warning on line 16 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <csignal> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iostream>

Check warning on line 17 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <iostream> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <X11/Xlib.h>

Check warning on line 19 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <X11/Xlib.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "applet.h"

Check warning on line 21 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "applet.h" not found.
#include "containment.h"

Check warning on line 22 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "containment.h" not found.
#include "pluginloader.h"

Check warning on line 23 in shell/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "pluginloader.h" not found.
#include "appletloader.h"
#include "qmlengine.h"
#include "shell.h"
Expand Down Expand Up @@ -46,6 +48,28 @@
QLoggingCategory::setFilterRules("*.debug=false");
}

// Handle X server disconnection gracefully.
// When X server is killed (e.g. init 3), libX11's _XDefaultIOError calls exit(),
// bypassing Qt's normal shutdown. This causes plugins to be destroyed during global
// destructors when objects are already partially destroyed, leading to SIGSEGV.
//
// By installing a custom X I/O error handler, we prevent exit() from being called
// and instead trigger a clean Qt shutdown via quit(), which fires aboutToQuit
// and allows plugins to be properly destroyed.
static int xio_error_handler(Display * /*dpy*/)
{
qCCritical(dsLog) << "X I/O error detected, shutting down gracefully.";
QCoreApplication::quit();
return 0;
}

static void sigpipe_handler(int /*sig*/)
{
// 信号处理函数中禁止调用非异步信号安全函数(如 qCCritical),
// 否则在持有相关锁时触发信号会导致死锁。
QCoreApplication::quit();
}

class AppletManager
{
public:
Expand Down Expand Up @@ -218,5 +242,19 @@
manager.quit();
});

// Install X11-specific error handlers to prevent exit() from being called
// when X server is killed (e.g. during init 3 → init 5 switch).
// On Wayland, these are not needed as the error path is different.
if (QGuiApplication::platformName().startsWith(QStringLiteral("xcb"))) {
XSetIOErrorHandler(xio_error_handler);

struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigpipe_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGPIPE, &sa, nullptr);
}

return a.exec();
}
Loading