Skip to content

fix: possible proxy model desync bug on model reset - #1695

Merged
BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:fixfix
Nov 9, 2026
Merged

BLumia merged 1 commit into
linuxdeepin:masterfrom
BLumia:fixfix

Conversation

@BLumia

@BLumia BLumia commented Aug 10, 2026 •

Copy link
Copy Markdown
Member

Bug 1 (RoleCombineModel 缺少 modelReset 转发) — 可触发

AbstractWindowMonitor::clearTrackedWindows() 会调用 beginResetModel() / endResetModel(),在以下时机被调用:

treelandwindowmonitor.cpp:105 和 x11windowmonitor.cpp:94 — 当显示服务器重连或 compositor 重启时,窗口监视器会清空所有跟踪窗口并复位模型 这个 modelReset 会穿过 BoolFilterModel 到达 RoleCombineModel 的 major model。修复前,复位后 m_indexMap 残留旧映射且下游收不到 reset 信号,导致新旧数据冲突。这是一个生产环境可触发的 bug。

Bug 2 (RoleGroupModel rowsRemoved 跳过后续分组) — 当前不可触发,属于防御性修复

RoleGroupModel 的源模型是 DockGlobalElementModel,其所有删除路径(destroyWindow 单窗口关闭、DockGlobalElementModel 内部循环)都是逐个调用 beginRemoveRows(pos, pos) / endRemoveRows(),每次只有 first == last。因此 range 分支在当前代码中永远不会被执行,--i 缺失不会造成问题。但 handler 的接口签名支持 first..last 范围,LargeDataMemoryStabilityTest 测试也直接传入了范围,若未来有代码路径直接传入多行范围,就会触发。这是一个防御性修复。

Log:

Summary by Sourcery

Keep proxy models synchronized across source resets and grouped-row removals.

Bug Fixes:

  • Forward source model resets through RoleCombineModel while rebuilding mappings to prevent stale data and downstream desynchronization.
  • Correct RoleGroupModel range-removal handling so subsequent groups remain synchronized after batch deletions.

Tests:

  • Add coverage for combined-model reset handling and grouped-model range removals and data-change propagation.

@BLumia
BLumia requested a review from Ivy233 August 10, 2026 02:21

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @BLumia, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@sourcery-ai

sourcery-ai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Implementation

Rebuild RoleCombineModel’s index map and emit modelReset when the major source resets, preventing stale mappings from surviving a reset.

  • panels/dock/taskmanager/rolecombinemodel.cpp L161-177

Adjust the rowsRemoved iteration after deleting an empty group so a subsequent group is not skipped when handling a multi-row removal.

  • panels/dock/taskmanager/rolegroupmodel.cpp L91

Tests

Add reset helpers and tests covering RoleCombineModel behavior after major and minor source model resets.

  • tests/panels/dock/taskmanager/combinemodela.cpp L110-117
  • tests/panels/dock/taskmanager/combinemodela.h L45
  • tests/panels/dock/taskmanager/combinemodelb.cpp L110-117
  • tests/panels/dock/taskmanager/combinemodelb.h L44
  • tests/panels/dock/taskmanager/rolecombinemodeltests.cpp L414-507

Add coverage for range-based row removal and child-level dataChanged indexes in RoleGroupModel.

  • tests/panels/dock/taskmanager/rolegroupmodeltests.cpp L637-738

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-bot

deepin-bot Bot commented Aug 18, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.53
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1702

@deepin-bot

deepin-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.54
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1733

@deepin-bot

deepin-bot Bot commented Sep 22, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.55
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1752

@deepin-bot

deepin-bot Bot commented Sep 23, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.56
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1753

@deepin-bot

deepin-bot Bot commented Oct 12, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.57
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1758

@deepin-bot

deepin-bot Bot commented Oct 15, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.58
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1765

@deepin-bot

deepin-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.59
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1766

@deepin-bot

deepin-bot Bot commented Oct 20, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.60
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1773

@deepin-bot

deepin-bot Bot commented Oct 28, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 2.0.61
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1786

wjyrich
wjyrich previously approved these changes Nov 9, 2026
Bug 1 (RoleCombineModel 缺少 modelReset 转发) — 可触发

AbstractWindowMonitor::clearTrackedWindows() 会调用 beginResetModel() / endResetModel(),在以下时机被调用:

treelandwindowmonitor.cpp:105 和 x11windowmonitor.cpp:94 — 当显示服务器重连或 compositor 重启时,窗口监视器会清空所有跟踪窗口并复位模型
这个 modelReset 会穿过 BoolFilterModel 到达 RoleCombineModel 的 major model。修复前,复位后 m_indexMap 残留旧映射且下游收不到 reset 信号,导致新旧数据冲突。这是一个生产环境可触发的 bug。

Bug 2 (RoleGroupModel rowsRemoved 跳过后续分组) — 当前不可触发,属于防御性修复

RoleGroupModel 的源模型是 DockGlobalElementModel,其所有删除路径(destroyWindow 单窗口关闭、DockGlobalElementModel 内部循环)都是逐个调用 beginRemoveRows(pos, pos) / endRemoveRows(),每次只有 first == last。因此 range 分支在当前代码中永远不会被执行,--i 缺失不会造成问题。但 handler 的接口签名支持 first..last 范围,LargeDataMemoryStabilityTest 测试也直接传入了范围,若未来有代码路径直接传入多行范围,就会触发。这是一个防御性修复。

Log:
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 96 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 该 PR 修复了 RoleCombineModel 在源模型 modelReset 时 m_indexMap 不同步的 Bug(新增 modelReset 信号转发与索引重建),以及 RoleGroupModel 批量删除时迭代跳过的经典 Bug(--i 修复)。生产代码修复逻辑正确,测试覆盖了主要场景。OCR 发现测试代码中存在过时 BUG 注释和 MinorModelResetForwarding 测试设计缺陷(因巧合通过、未真正验证 Bug),建议修正。无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无']


2. 代码质量 ✅

评价: 代码结构清晰,注释基本完整,存在少量测试注释问题 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ["更新 rolecombinemodeltests.cpp 第139行注释,移除'BUG: 当前实现不会发出此信号,此断言会 FAIL',改为说明修复后的预期行为", '增强 MinorModelResetForwarding 测试:要么在实现中添加 minor modelReset 连接并用 QSignalSpy 验证,要么使用不同索引的数据使测试能真正暴露 stale mapping 问题', '考虑将测试注释翻译为英文以保持代码库风格一致']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无']


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: ['无']


💡 改进建议代码示例

// 修复 1: 更新过时的 BUG 注释 (rolecombinemodeltests.cpp)
// 将第139行:
//   // BUG: 当前实现不会发出此信号,此断言会 FAIL
//   EXPECT_EQ(resetSpy.count(), 1) << "FAIL: RoleCombineModel did not forward modelReset from major source";
// 改为:
//   // 修复后: RoleCombineModel 现在会转发 major 源的 modelReset 信号
//   EXPECT_EQ(resetSpy.count(), 1) << "RoleCombineModel should forward modelReset from major source";

// 修复 2: 增强 MinorModelResetForwarding 测试,使用不同索引暴露 stale mapping
TEST(RoleCombineModel, MinorModelResetForwarding)
{
    TestModelA modelA;
    TestModelB modelB;

    auto combineFunc = [](QVariant data, QAbstractItemModel *model) -> QModelIndex {
        auto matches = model->match(model->index(0, 0), TestModelB::idRole, data);
        return matches.isEmpty() ? QModelIndex() : matches.first();
    };

    RoleCombineModel model(&modelA, &modelB, TestModelA::idRole, combineFunc);

    modelA.addData(new DataA(0, "a0", &modelA));
    modelA.addData(new DataA(1, "a1", &modelA));
    modelB.addData(new DataB(0, "b0", &modelB));
    modelB.addData(new DataB(1, "b1", &modelB));

    ASSERT_EQ(model.rowCount(), 2);

    // 清空 minor 后用不同数据重新填充,暴露 stale mapping
    modelB.clear();
    modelB.addData(new DataB(0, "b0_new", &modelB));
    modelB.addData(new DataB(1, "b1_new", &modelB));

    auto roleNames = model.roleNames();
    auto roleNamesB = modelB.roleNames();
    QHash<QByteArray, int> names2Role;
    for (auto it = roleNames.constBegin(); it != roleNames.constEnd(); ++it) {
        names2Role.insert(it.value(), it.key());
    }
    int bDataRole = names2Role.value(roleNamesB.value(TestModelB::dataRole));

    // 若 minor modelReset 未连接,m_indexMap 保留旧映射,
    // 新数据可能无法正确映射——此断言会暴露问题
    EXPECT_EQ(model.index(0, 0).data(bDataRole).toString(), "b0_new");
    EXPECT_EQ(model.index(1, 0).data(bDataRole).toString(), "b1_new");
}

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: BLumia, wjyrich

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

@BLumia
BLumia merged commit 7f8faa8 into linuxdeepin:master Nov 9, 2026
5 of 8 checks passed
@BLumia
BLumia deleted the fixfix branch November 9, 2026 07:43
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