Skip to content

feat: add post-upgrade check for Wayland in treeland environment#305

Merged
xionglinlin merged 1 commit into
linuxdeepin:masterfrom
xionglinlin:master
Jun 3, 2026
Merged

feat: add post-upgrade check for Wayland in treeland environment#305
xionglinlin merged 1 commit into
linuxdeepin:masterfrom
xionglinlin:master

Conversation

@xionglinlin
Copy link
Copy Markdown
Contributor

  1. Add isWayland and postUpdateCheckCompleted properties to UpdateModel with QML bindings
  2. Implement doCheckSystemOnWayland in UpdateWorker to perform staged system check (CSS_BeforeLogin → CSS_AfterLogin) after upgrade completion
  3. Update desktop autostart entry to skip dde-update process under Wayland, preventing restart issues
  4. Modify QML UI to show busy state during post-update check and bypass backup dialog for Wayland
  5. This solves the issue where dde-update fails to start after system restart in treeland environment, ensuring system integrity via staged verification

Log: Added post-upgrade system check feature for Wayland to ensure proper system functionality after updates

Influence:

  1. Test upgrade on X11 environment to verify no regression (postUpdateCheckCompleted remains true)
  2. Test upgrade on treeland/Wayland environment to verify staged check runs correctly
  3. Verify busy indicator shows during check and hides after completion
  4. Test upgrade failure scenario to ensure check completes even on error
  5. Verify dde-update autostart is disabled under Wayland
  6. Test multiple consecutive upgrades to ensure check state resets properly

feat: 为 Wayland 环境(treeland)添加更新后系统检查功能

  1. 为 UpdateModel 添加 isWayland 和 postUpdateCheckCompleted 属性及 QML 绑定
  2. 在 UpdateWorker 中实现 doCheckSystemOnWayland 方法,在更新完成后分阶 段执行系统检查(CSS_BeforeLogin → CSS_AfterLogin)
  3. 更新桌面自动启动条目,在 Wayland 环境下跳过 dde-update 进程,避免重启 问题
  4. 修改 QML UI 在更新后检查期间显示繁忙状态,并在 Wayland 下跳过备份对 话框
  5. 解决 treeland 环境下系统重启后 dde-update 无法启动的问题,通过分阶段 验证确保系统完整性

Log: 新增 Wayland 环境下的更新后系统检查功能,确保系统正常运行

Influence:

  1. 测试 X11 环境下的升级功能,确认无回归(postUpdateCheckCompleted 保持 为 true)
  2. 测试 treeland/Wayland 环境下的升级功能,确认分阶段检查正确执行
  3. 验证检查期间显示繁忙指示器,完成后隐藏
  4. 测试升级失败场景,确保即使出错检查也能完成
  5. 验证 Wayland 下 dde-update 自动启动被禁用
  6. 测试多次连续升级,确保检查状态正确重置

PMS: BUG-347525 BUG-347529
Change-Id: I832f7c7c55dd13158d13f0c3d25478030a39999c

1. Add `isWayland` and `postUpdateCheckCompleted` properties to
UpdateModel with QML bindings
2. Implement `doCheckSystemOnWayland` in UpdateWorker to perform staged
system check (CSS_BeforeLogin → CSS_AfterLogin) after upgrade completion
3. Update desktop autostart entry to skip dde-update process under
Wayland, preventing restart issues
4. Modify QML UI to show busy state during post-update check and bypass
backup dialog for Wayland
5. This solves the issue where dde-update fails to start after system
restart in treeland environment, ensuring system integrity via staged
verification

Log: Added post-upgrade system check feature for Wayland to ensure
proper system functionality after updates

Influence:
1. Test upgrade on X11 environment to verify no regression
(postUpdateCheckCompleted remains true)
2. Test upgrade on treeland/Wayland environment to verify staged check
runs correctly
3. Verify busy indicator shows during check and hides after completion
4. Test upgrade failure scenario to ensure check completes even on error
5. Verify dde-update autostart is disabled under Wayland
6. Test multiple consecutive upgrades to ensure check state resets
properly

feat: 为 Wayland 环境(treeland)添加更新后系统检查功能

1. 为 UpdateModel 添加 isWayland 和 postUpdateCheckCompleted 属性及 QML
绑定
2. 在 UpdateWorker 中实现 doCheckSystemOnWayland 方法,在更新完成后分阶
段执行系统检查(CSS_BeforeLogin → CSS_AfterLogin)
3. 更新桌面自动启动条目,在 Wayland 环境下跳过 dde-update 进程,避免重启
问题
4. 修改 QML UI 在更新后检查期间显示繁忙状态,并在 Wayland 下跳过备份对
话框
5. 解决 treeland 环境下系统重启后 dde-update 无法启动的问题,通过分阶段
验证确保系统完整性

Log: 新增 Wayland 环境下的更新后系统检查功能,确保系统正常运行

Influence:
1. 测试 X11 环境下的升级功能,确认无回归(postUpdateCheckCompleted 保持
为 true)
2. 测试 treeland/Wayland 环境下的升级功能,确认分阶段检查正确执行
3. 验证检查期间显示繁忙指示器,完成后隐藏
4. 测试升级失败场景,确保即使出错检查也能完成
5. 验证 Wayland 下 dde-update 自动启动被禁用
6. 测试多次连续升级,确保检查状态正确重置

PMS: BUG-347525 BUG-347529
Change-Id: I832f7c7c55dd13158d13f0c3d25478030a39999c
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这份代码变更主要为了解决在 Wayland (Treeland) 环境下,系统更新后无法正常启动 dde-update 进程的问题。采用的替代方案是在更新完成后,由 DCC 控制端串行调用 CheckUpgrade 的两个阶段(CSS_BeforeLogin 和 CSS_AfterLogin),并在 QML 界面上通过 busyState 阻止用户在检查完成前重启。

整体逻辑清晰,但存在一些逻辑漏洞、内存泄漏风险、线程安全隐患及代码规范问题。以下是详细的审查意见:

1. 逻辑漏洞:status == "succeed" 被忽略导致流程中断

文件: src/dcc-update-plugin/operation/updatework.cpp
位置: onCheckSystemJobStatusChanged 函数

问题:
在判断 Stage 1 是否完成的逻辑中,只处理了 "failed""end" 状态,遗漏了 "succeed" 状态。如果底层的 DBus 返回的状态是 "succeed",该条件分支将不会执行任何操作,导致 Stage 2 永远不会触发,m_postUpdateCheckCompleted 永远不会被置为 true,UI 将无限期处于忙碌(转圈)状态,阻塞用户重启。

改进建议:
将 Stage 1 的完成条件放宽,只要不是 "failed",都应该继续推进到 Stage 2。

// 修改前
if (m_currentCheckStage == 1) {
    if (status == "failed") {
        qCWarning(...) << "...";
        m_model->setPostUpdateCheckCompleted(true);
        return;
    } else if (status == "end") {
        // CSS_BeforeLogin 阶段完成,继续 CSS_AfterLogin 阶段
        ...
    }
}

// 修改后
if (m_currentCheckStage == 1) {
    if (status == "failed") {
        qCWarning(...) << "...";
        m_model->setPostUpdateCheckCompleted(true);
        return;
    } else if (status == "succeed" || status == "end") {
        // CSS_BeforeLogin 阶段完成,继续 CSS_AfterLogin 阶段
        qCInfo(logDccUpdatePlugin) << "treeland: CSS_BeforeLogin completed, starting CSS_AfterLogin";
        QTimer::singleShot(1000, this, [this] {
            doCheckSystemOnWayland(2);
        });
    }
}

2. 代码性能与安全:QPointercleanLaStoreJob 的使用冲突

文件: src/dcc-update-plugin/operation/updatework.cpp
位置: setCheckSystemJobonCheckSystemJobStatusChanged

问题:

  1. m_checkSystemJob 声明为 QPointer<UpdateJobDBusProxy>QPointer 会在对象被销毁时自动置为 nullptr
  2. cleanLaStoreJob 的内部实现大概率是 delete job; job = nullptr;(或者类似的清理逻辑)。
  3. setCheckSystemJob 中,如果 m_checkSystemJob 非空,直接调用了 m_model->setPostUpdateCheckCompleted(true);return但没有清理原有的 Job,这可能导致旧 Job 的信号依然挂在循环中,引发意外回调。
  4. onCheckSystemJobStatusChanged 中,调用 cleanLaStoreJob(m_checkSystemJob); 后,m_checkSystemJob 变为 nullptr。紧接着如果 Stage 1 完成,1秒后触发 doCheckSystemOnWayland(2),在 setCheckSystemJob 中会重新 new 一个 Job。这个生命周期管理比较脆弱。

改进建议:
确保在放弃或替换 Job 时,先进行清理。同时,建议在 cleanLaStoreJob 之后断开可能残留的信号连接(防御性编程)。

void UpdateWorker::setCheckSystemJob(const QString& jobPath)
{
    qCInfo(logDccUpdatePlugin) << "Create check system job, path:" << jobPath;
    if (jobPath.isEmpty()) {
        qCWarning(logDccUpdatePlugin) << "Check system job path is empty";
        m_model->setPostUpdateCheckCompleted(true);
        return;
    }
    
    // 如果已存在正在运行的 Job,先清理
    if (m_checkSystemJob) {
        qCWarning(logDccUpdatePlugin) << "Check system job already exists, cleaning old one";
        cleanLaStoreJob(m_checkSystemJob);
    }

    m_checkSystemJob = new UpdateJobDBusProxy(jobPath, this);
    connect(m_checkSystemJob, &UpdateJobDBusProxy::StatusChanged, this, &UpdateWorker::onCheckSystemJobStatusChanged);
    onCheckSystemJobStatusChanged(m_checkSystemJob->status());
}

3. 线程安全与状态一致性:m_updateMode 的异步赋值

文件: src/dcc-update-plugin/operation/updatework.cpp
位置: doUpgrade 函数

问题:

if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
    m_updateMode = updateTypes;
    m_model->setPostUpdateCheckCompleted(false);
}

QDBusPendingCall call = m_updateInter->DistUpgradePartly(updateTypes, doBackup);

m_updateMode 在这里被赋值,并在稍后的异步回调 doCheckSystemOnWayland 中作为参数传递给 DBus:m_updateInter->CheckUpgrade(m_updateMode, stage)
虽然目前 Qt 的事件循环确保了这些逻辑都在主线程,但 m_updateMode 作为一个成员变量,生命周期跨越了整个升级过程,如果用户在升级过程中(虽然UI可能被锁定)触发了其他操作改变了 updateTypes,或者并发调用了 doUpgradem_updateMode 就会被污染,导致传给 CheckUpgrade 的模式不正确。

改进建议:
作为局部状态传递,建议使用 Lambda 的值捕获,而不是持久化到成员变量。如果必须使用成员变量,需确保逻辑上不会并发重入。

// 如果必须保留成员变量,建议重置逻辑更严谨
// 在 doUpgrade 开始时:
m_updateMode = updateTypes; // 无论是否 Wayland,同步更新模式都是合理的

// 更好的做法:如果 doCheckSystemOnWayland 只依赖当次 doUpgrade 的 updateTypes,
// 可以考虑将 updateTypes 保存在发起请求时的上下文中,而不是全局的 m_updateMode。

4. 代码规范:魔法数字 与 注释不一致

文件: src/dcc-update-plugin/operation/updatework.cpp & updatework.h

问题:

  1. doCheckSystemOnWayland(1)doCheckSystemOnWayland(2) 中的 12 是典型的魔法数字。虽然注释解释了 1=CSS_BeforeLogin, 2=CSS_AfterLogin,但在代码中直接使用数字不利于维护。
  2. 头文件中 m_currentCheckStage 的注释与代码逻辑存在轻微歧义。

改进建议:
使用 enumstatic const int 替代魔法数字。

// 在 updatework.h 或 .cpp 顶部定义
enum CheckSystemStage {
    CSS_BeforeLogin = 1,
    CSS_AfterLogin = 2
};

// 调用处修改为:
doCheckSystemOnWayland(CSS_BeforeLogin);
// ...
doCheckSystemOnWayland(CSS_AfterLogin);

// 成员变量注释更新
int m_currentCheckStage = 0; // 当前 check system 阶段: 0=None, CSS_BeforeLogin, CSS_AfterLogin

5. 代码安全:Shell 注入与环境变量检测

文件: src/dde-update/misc/dde-update-autostart.desktop

问题:

Exec=sh -c 'if [ -f /tmp/deepin_update_option.json ] && [ "$XDG_SESSION_TYPE" != "wayland" ]; then /usr/bin/dde-update ; fi'
  1. 这里读取 /tmp 下的文件来决定是否执行更新,存在一定的安全隐患(任何用户都可以在 /tmp 创建该文件)。但这属于历史遗留问题。
  2. $XDG_SESSION_TYPE 的判断逻辑是正确的,但需确保在 dde-update 的启动环境中,该环境变量确实已被正确设置。通常在 X11/Wayland 会话中它是可靠的。

改进建议:
针对安全风险,建议在 C++ 代码层面(如 dde-update 进程启动初)也增加对 Wayland 环境的判断并主动退出,而不是完全依赖 .desktop 文件的 Shell 判断,以防止被手动执行:

// dde-update 主函数中建议增加防御:
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
    qWarning() << "dde-update is not supported on Wayland, aborting.";
    return 0;
}

6. 代码逻辑:QML 端的硬编码平台判断

文件: src/dcc-update-plugin/qml/UpdateMain.qml

问题:

if (DccApp.isTreeland()) {
    dccData.work().doUpgrade(updateType, true)
} else {
    updateSelectLoader.updateType = updateType
    updateSelectLoader.active = true
}

在 QML 中使用 DccApp.isTreeland() 进行了硬编码的平台判断,导致在 Wayland 下跳过了 updateSelectLoader 的交互逻辑,直接强制 doBackup=true 进行升级。这剥夺了 Wayland 用户选择是否备份的机会。

改进建议:
确认产品需求:Wayland 下是否真的不需要用户确认备份?
如果需要确认,应该弹出对应对话框,而不是直接 doUpgrade(updateType, true)。如果是因为 Wayland 下备份逻辑有 Bug 而暂时绕过,请添加 // TODO: 注释说明后续修复计划。

总结

最严重的问题是第1点(逻辑漏洞),它会导致特定情况下 UI 死锁。建议优先修复状态判断逻辑,并顺带优化魔法数字和 Job 的生命周期管理。其余部分架构合理,修复后即可达到生产环境代码质量要求。

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mhduiy, xionglinlin

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@xionglinlin xionglinlin merged commit d35c822 into linuxdeepin:master Jun 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants