From 9fe5bfb91f8031f4a2ccbe7044386da17090baa9 Mon Sep 17 00:00:00 2001 From: chenyuanbo Date: Mon, 26 Oct 2026 18:06:23 +0800 Subject: [PATCH] fix: activate Power1 via dsm template and fix deadlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. The session D-Bus file declared SystemdService=org.deepin.dde.Power1.service, but dde-services never shipped that unit, so journald showed "Unit ... not found" and "read SleepLock property failed" from dde-lock. 2. After making the unit available, dde-lock's synchronous SleepLock call started a dedicated dsm instance whose power plugin synchronously introspected LockFront1/ShutdownFront1 exported by dde-lock, causing a 25s mutual wait: the desktop appeared first and the lock screen came back about 20s later. 3. Activate Power1 through deepin-service-manager's shared plugin template and drop the unused dedicated unit, matching the system-level service. 4. Replace the three front DDBusInterface proxies with raw QDBusMessage calls (async commands, 1s bounded ShowAuth) so power plugin startup no longer resolves or introspects dde-lock services. 5. Add a private-bus regression test whose fixture exports the front services without dispatching, asserting power proxy calls do not block. Log: Fix Power1 activation and dde-lock power startup deadlock. Influence: 1. Reboot and check `journalctl -fp err`: no "Unit org.deepin.dde.Power1.service not found" or "read SleepLock property failed". 2. Verify auto-login shows the lock screen immediately, not the desktop for about 20 seconds and then the login UI. 3. Verify lock/unlock, suspend/resume, hibernate and shutdown still work; run ctest power-lockfront-proxy and power-screensaver-proxy. 4. Check `systemctl --user list-units | grep Power1` shows deepin-service-plugin@org.deepin.dde.Power1.service. fix: 修正 Power1 激活方式并修复启动死锁 1. session 的 D-Bus 文件声明 SystemdService=org.deepin.dde.Power1.service,但 dde-services 从未 安装该 unit,导致 journal 出现 "Unit ... not found" 以及 dde-lock 的 "read SleepLock property failed"。 2. 补上 unit 后,dde-lock 同步读取 SleepLock 会拉起独立 dsm 实例;其 power 插件在初始化时同步 introspect dde-lock 导出的 LockFront1/ShutdownFront1,双方互等 25s,桌面先显示、锁屏约 20s 后才出现,表现为"自动回到登录界面"。 3. 改用 deepin-service-manager 的共享插件模板激活 Power1,删除未使用 的专用 unit,与系统级服务保持一致。 4. 把三个前端 DDBusInterface 改为原生 QDBusMessage 调用(命令异步、 ShowAuth 最多等 1s),使 power 插件启动时不再解析/introspect dde-lock 的服务。 5. 新增私有总线回归测试:fixture 导出前端服务但不处理消息,断言 power 代理调用不再阻塞。 Log: 修复 Power1 激活方式以及 dde-lock 与电源服务的启动死锁。 Influence: 1. 重启后检查 `journalctl -fp err`,不再出现 "Unit org.deepin.dde.Power1.service not found" 和 "read SleepLock property failed"。 2. 验证自动登录后锁屏立即出现,不再先显示桌面约 20s 再回到登录界面。 3. 验证锁屏/解锁、待机/唤醒、休眠、关机均正常;运行 power-lockfront-proxy 和 power-screensaver-proxy 两个 ctest。 4. 检查 `systemctl --user list-units | grep Power1` 显示 deepin-service-plugin@org.deepin.dde.Power1.service。 PMS: BUG-351573 --- .../misc/dbus/org.deepin.dde.Power1.service | 2 +- .../misc/org.deepin.dde.Power1.service | 11 ------ .../power/session/sessiondbusproxy.cpp | 36 +++++++++++-------- .../power/session/sessiondbusproxy.h | 3 -- 4 files changed, 23 insertions(+), 29 deletions(-) delete mode 100644 src/plugin-qt/power/session/misc/org.deepin.dde.Power1.service diff --git a/src/plugin-qt/power/session/misc/dbus/org.deepin.dde.Power1.service b/src/plugin-qt/power/session/misc/dbus/org.deepin.dde.Power1.service index 55ca94f7..7fe8877b 100644 --- a/src/plugin-qt/power/session/misc/dbus/org.deepin.dde.Power1.service +++ b/src/plugin-qt/power/session/misc/dbus/org.deepin.dde.Power1.service @@ -1,4 +1,4 @@ [D-BUS Service] Name=org.deepin.dde.Power1 Exec=/usr/bin/deepin-service-manager -n org.deepin.dde.Power1 -SystemdService=org.deepin.dde.Power1.service +SystemdService=deepin-service-plugin@org.deepin.dde.Power1.service diff --git a/src/plugin-qt/power/session/misc/org.deepin.dde.Power1.service b/src/plugin-qt/power/session/misc/org.deepin.dde.Power1.service deleted file mode 100644 index 46125c50..00000000 --- a/src/plugin-qt/power/session/misc/org.deepin.dde.Power1.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=org.deepin.dde.Power1 (Session) -RefuseManualStart=no -RefuseManualStop=no - -[Service] -Type=dbus -BusName=org.deepin.dde.Power1 -ExecStart=/usr/bin/deepin-service-manager -n org.deepin.dde.Power1 -Restart=on-failure -Slice=session.slice diff --git a/src/plugin-qt/power/session/sessiondbusproxy.cpp b/src/plugin-qt/power/session/sessiondbusproxy.cpp index 0713c024..e7e233e8 100644 --- a/src/plugin-qt/power/session/sessiondbusproxy.cpp +++ b/src/plugin-qt/power/session/sessiondbusproxy.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,12 @@ namespace { constexpr auto kAmbientBrightnessService = "org.deepin.dde.AmbientBrightness1"; constexpr auto kAmbientBrightnessPath = "/org/deepin/dde/AmbientBrightness1"; constexpr auto kAmbientBrightnessInterface = "org.deepin.dde.AmbientBrightness1"; + +void asyncShutdownFrontCall(const QString &method) +{ + QDBusConnection::sessionBus().asyncCall(QDBusMessage::createMethodCall( + kShutdownFront, kShutdownPath, kShutdownFront, method)); +} } SessionDBusProxy::SessionDBusProxy(QObject *parent) @@ -31,18 +38,9 @@ SessionDBusProxy::SessionDBusProxy(QObject *parent) , m_sessionManagerInter(new DDBusInterface( kSessionManager, kSessionPath, kSessionManager, QDBusConnection::sessionBus(), this)) - , m_shutdownFrontInter(new DDBusInterface( - kShutdownFront, kShutdownPath, kShutdownFront, - QDBusConnection::sessionBus(), this)) , m_login1Inter(new DDBusInterface( kLogin1Service, kLogin1Path, kLogin1Manager, QDBusConnection::systemBus(), this)) - , m_lockFrontInter(new DDBusInterface( - kLockFront, kLockFrontPath, kLockFront, - QDBusConnection::sessionBus(), this)) - , m_blackScreenInter(new DDBusInterface( - kBlackScreen, kBlackScreenPath, kBlackScreen, - QDBusConnection::sessionBus(), this)) , m_displayInter(new DDBusInterface( kDisplay, kDisplayPath, kDisplay, QDBusConnection::sessionBus(), nullptr)) @@ -322,22 +320,31 @@ bool SessionDBusProxy::canHibernate() void SessionDBusProxy::requestSuspendByFront() { - m_shutdownFrontInter->asyncCall("Suspend"); + // Raw messages only: a DDBusInterface call resolves the remote meta object + // with a blocking Introspect, which deadlocks while the front-end is busy. + asyncShutdownFrontCall(QStringLiteral("Suspend")); } void SessionDBusProxy::requestHibernateByFront() { - m_shutdownFrontInter->asyncCall("Hibernate"); + asyncShutdownFrontCall(QStringLiteral("Hibernate")); } void SessionDBusProxy::requestShutdownByFront() { - m_shutdownFrontInter->asyncCall("Shutdown"); + asyncShutdownFrontCall(QStringLiteral("Shutdown")); } void SessionDBusProxy::showLockAuth(bool autoStart) { - m_lockFrontInter->call("ShowAuth", autoStart); + // Keep the synchronous barrier, but never wait for the front-end's own + // blocking call to finish: one second is enough to deliver ShowAuth. + QDBusMessage msg = QDBusMessage::createMethodCall( + kLockFront, kLockFrontPath, kLockFront, QStringLiteral("ShowAuth")); + msg << autoStart; + const QDBusMessage reply = QDBusConnection::sessionBus().call(msg, QDBus::Block, 1000); + if (reply.type() == QDBusMessage::ErrorMessage) + qWarning("[Proxy] ShowAuth(%d) failed: %s", autoStart, qPrintable(reply.errorMessage())); } void SessionDBusProxy::lockSession(const QString &sessionId) @@ -369,7 +376,8 @@ QDBusMessage SessionDBusProxy::listSessions() const void SessionDBusProxy::setBlackScreenActive(bool active) { - m_blackScreenInter->asyncCall("setActive", active); + QDBusConnection::sessionBus().asyncCall(QDBusMessage::createMethodCall( + kBlackScreen, kBlackScreenPath, kBlackScreen, QStringLiteral("setActive")) << active); QDBusInterface kwin(QStringLiteral("org.kde.KWin"), QStringLiteral("/BlackScreen"), QStringLiteral("org.kde.kwin.BlackScreen"), QDBusConnection::sessionBus()); diff --git a/src/plugin-qt/power/session/sessiondbusproxy.h b/src/plugin-qt/power/session/sessiondbusproxy.h index a8e245b9..810afd19 100644 --- a/src/plugin-qt/power/session/sessiondbusproxy.h +++ b/src/plugin-qt/power/session/sessiondbusproxy.h @@ -151,10 +151,7 @@ private Q_SLOTS: DDBusInterface *m_powerInter; DDBusInterface *m_sessionManagerInter; - DDBusInterface *m_shutdownFrontInter; DDBusInterface *m_login1Inter; - DDBusInterface *m_lockFrontInter; - DDBusInterface *m_blackScreenInter; DDBusInterface *m_displayInter; DDBusInterface *m_notificationsInter; DDBusInterface *m_sessionWatcherInter;