Skip to content
Open
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
41 changes: 31 additions & 10 deletions docs/design.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
lightdm 在认证通过以后,会启动 dde-session,dde-session 会通过 systemd 的 dbus 启动 org.deepin.dde.Session1.service
# 会话与 systemd 生命周期

在 org.deepin.dde.Session1.service 中会执行 dde-session-ctl --systemd-service,启动 dde-session-x11.target.
LightDM 认证通过后启动 `dde-session`。入口进程导入会话环境,启动
`dde-session.target`,并监听 `org.deepin.dde.Session1` 的注销。
`dde-session-manager.service` 通过 loader wrapper 运行
`dde-session --systemd-service`,注册 Session1 等 D-Bus 接口。
会话按 pre、core、initialized 阶段启动,依赖关系以 `systemd/` 中的单元为准。

注销会话有两个入口,一个是 lightdm 停止会话,那么就需要一种途径去关闭启动的 session 相关的 services。
另外一个是主动启动 dde-session-shutdown.service,在 service 中会执行 dde-session-ctl --shutdown,去开启 dde-session-shutdown.target,在这个
target中关联了所有服务的冲突,这样其它服务就会被关闭,等执行完毕,所有的服务都将会退出。
## 桌面、Dock 和托盘

在一些核心的服务上也会关联上 dde-session-shutdown.service。
core 阶段并行启动桌面 `dde-shell-plugin@org.deepin.ds.desktop.service` 和
任务栏 `dde-shell@DDE.service`;两者之间没有启动或停止顺序约束。
任务栏属于 dde-shell 的 DDE 分组,不再由旧的 `dde-dock.service` 管理。

在 dde-session-manager.service 的 ExecStop 执行 /usr/libexec/dde-session-ctl --logout,这个命令会
调用 org.deepin.dde.Session1.Logout() 方法,把阻塞 lightdm 的 会话入口退出,当 org.deepin.dde.Session1 服务在 DBus 上消失时,关联的 org.deepin.dde.Session1.service 服务就会停止,从而执行 /usr/libexec/dde-session-ctl --shutdown,去启动 dde-session-shutdown.target,将所有 DDE 服务冲突掉,从而完成关闭,在最后阶段,dde-session-shutdown.target 会启动 dde-session-restart-dbus.service 去将 dbus.service 服务停止,完成最终的防止 dbus 服务进程逃逸。
Dock 通过 `Wants=dde-tray-loader.target` 启动托盘。配套 dde-tray-loader 中,
target 通过 `After=` 等待 Dock 的 `Type=dbus` 启动完成:Dock 的内部合成器
就绪后才注册 `org.deepin.dde.Dock1`。随后各托盘分组服务并行启动。
target 通过 `BindsTo=` 和 `PartOf=` 绑定 Dock,无需直接绑定 core 或额外的 ready 服务。

停止时依赖顺序反转,各托盘组并行退出后 Dock 才退出。桌面可以同时退出,
不会等待 Dock;慢托盘仍会延迟 Dock 停止。这些顺序不保证合成器窗口动画或
屏幕残影的消失顺序。托盘生命周期测试见 dde-tray-loader 的 README。

## 注销与异常退出

systemd unit图:
正常注销经过 SessionManager 的注销准备流程。`dde-session-ctl --logout`
则调用 Session1 的 `Logout()`。管理进程退出后,systemd 执行
`dde-session-manager.service` 的 `ExecStopPost=dde-session-ctl --shutdown`,
启动 `dde-session-shutdown.target`,利用冲突关系停止会话目标与服务。
也可以通过 `dde-session-shutdown.service` 请求同一关闭流程。

![](images/dde-session-services.png)
管理进程被终止或崩溃时,`ExecStopPost` 仍执行清理,`OnFailure` 还会触发
shutdown target。因此无需在 POSIX 信号处理函数中调用 Qt 或 D-Bus;
此类重入可能等待被中断线程持有的锁,反而阻塞进程退出。

入口进程发现 Session1 总线名称消失后,启动 `dde-session-exit-task.service`
并退出,将控制权交回 LightDM。exit task 通过 `dde-session-ctl --session-exit`
在一秒延迟后停止用户 `dbus.service`。登录界面的后续启动与壁纸加载属于
LightDM/greeter 流程,应与会话服务的停止耗时分别排查。
29 changes: 0 additions & 29 deletions src/dde-session/impl/sessionmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#include <QTimer>

#include <unistd.h>
#include <signal.h>
#include <xcb/xcb.h>

using namespace Dtk::Core;
Expand Down Expand Up @@ -94,9 +93,6 @@ SessionManager::SessionManager(QObject *parent)
{
initConnections();

// 处理异常退出的情况
handleOSSignal();

auto appearanceConfig = DConfig::create("org.deepin.dde.appearance", "org.deepin.dde.appearance", QString(), this);
m_soundTheme = appearanceConfig->value("Sound_Theme", "deepin").toString();
connect(appearanceConfig, &DConfig::valueChanged, this, [this, appearanceConfig] (const QString &key) {
Expand Down Expand Up @@ -178,7 +174,6 @@ void SessionManager::prepareLogout(bool force)
stopBAMFDaemon();
stopRedshift();
stopObexService();
stopDock();

// 防止注销时,蓝牙音频设置没有断开连接
disconnectAudioDevices();
Expand Down Expand Up @@ -704,12 +699,6 @@ void SessionManager::stopRedshift()
VIEW_SERVICE(REDSHIFT_SERVICE);
}

void SessionManager::stopDock()
{
STOP_SERVICE(DDE_DOCK_SERVICE);
VIEW_SERVICE(DDE_DOCK_SERVICE);
}

void SessionManager::disconnectAudioDevices()
{
auto msg = QDBusInterface("org.deepin.dde.Bluetooth1"
Expand Down Expand Up @@ -864,24 +853,6 @@ void SessionManager::setDPMSMode(bool on)
}
}

/**
* @brief sig_crash 意外退出时处理一些事情
* @param sig 收到的异常退出信号类型
*/
[[noreturn]] void sig_crash(int sig) {
Q_UNUSED(sig);
SessionManager::instance()->doLogout();
exit(-1);
};

void SessionManager::handleOSSignal()
{
signal(SIGINT, sig_crash);
signal(SIGABRT, sig_crash);
signal(SIGTERM, sig_crash);
signal(SIGSEGV, sig_crash);
}

void SessionManager::setTlpMode(const QString &mode)
{
qInfo() << "setTlpMode mode:" << mode;
Expand Down
2 changes: 0 additions & 2 deletions src/dde-session/impl/sessionmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ public Q_SLOTS:
void stopPulseAudioService();
void stopBAMFDaemon();
void stopRedshift();
void stopDock();
void disconnectAudioDevices();

void preparePlayShutdownSound();
Expand All @@ -100,7 +99,6 @@ public Q_SLOTS:

void startBlackWidget();

void handleOSSignal();
void watchXConnection();

void shutdown(bool force);
Expand Down
3 changes: 1 addition & 2 deletions src/utils/utils.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

Expand All @@ -15,7 +15,6 @@
#define PIPEWIRE_PULSE_SOCKET "pipewire-pulse.socket"
#define BAMFDAEMON_SERVICE "bamfdaemon.service"
#define REDSHIFT_SERVICE "redshift.service"
#define DDE_DOCK_SERVICE "dde-dock.service"

// sound
#define SOUND_EFFECT_SCHEMA "com.deepin.dde.sound-effect"
Expand Down
9 changes: 5 additions & 4 deletions systemd/dde-session-core.target.wants/dde-shell@DDE.service
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ CollectMode=inactive-or-failed
Requisite=dde-session-pre.target
After=dde-session-pre.target

# Start alongside the desktop; neither service waits for the other
# during startup or shutdown.

PartOf=dde-session-core.target
Before=dde-session-core.target

Expand All @@ -17,11 +20,9 @@ After=dbus.socket
# AM
Wants=org.desktopspec.ApplicationManager1.service

# Tray plugin loader services (owned by dde-tray-loader). BusName is acquired
# only after the QML DockCompositor is ready, and Before= here ensures the
# dockplugin Wayland socket exists before the loaders start.
# The tray target orders itself after this Type=dbus service, which becomes
# active once the dock's internal compositor is ready.
Wants=dde-tray-loader.target
Before=dde-tray-loader.target

[Service]
Type=dbus
Expand Down
2 changes: 2 additions & 0 deletions systemd/dde-session-manager.service.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Type=forking
GuessMainPID=yes
ExecStart=@CMAKE_INSTALL_FULL_LIBEXECDIR@/deepin/dde-session-loader-wrapper --systemd-service
ExecStartPost=-/usr/bin/gdbus wait --session --timeout=30 org.deepin.dde.Session1
# Keep shutdown cleanup out of process signal handlers: Qt/D-Bus calls can
# deadlock there. ExecStopPost also runs after signal termination or a crash.
ExecStopPost=@CMAKE_INSTALL_FULL_LIBEXECDIR@/dde-session-ctl --shutdown
ExecStopPost=-/bin/sh -c 'test "$SERVICE_RESULT" != "exec-condition" && systemctl --user unset-environment XDG_CURRENT_DESKTOP'
ExecStopPost=-/bin/sh -c 'test "$SERVICE_RESULT" != "exec-condition" && systemctl --user unset-environment DISPLAY'
Expand Down
Loading