Skip to content

fix(dtkdeclarative): prevent startTimer warning when event dispatcher is unavailable - #657

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
52cyb:master
Aug 3, 2026
Merged

fix(dtkdeclarative): prevent startTimer warning when event dispatcher is unavailable#657
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
52cyb:master

Conversation

@52cyb

@52cyb 52cyb commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

DQuickDciIconImage::scheduleLayout() may be invoked via itemChange() or geometryChange() hooks during the destruction of ListView delegate items reparented to QCoreApplication via QQmlDelegateModel. At that point, ~QCoreApplication() has already set eventDispatcher to nullptr , causing QObject::startTimer() to emit:
"QObject::startTimer: Timers can only be used with threads started
with QThread"

Log: Fix startTimer warning for DciIcon

Influence:

  1. DciIcon displays correctly;
  2. When the program exits, DciIcon in containers such as ListView and Repeater does not have a startTimer warning

fix(dtkdeclarative): 修复 eventDispatcher 不可用时 startTimer 告警

ListView delegate item 经 QQmlDelegateModel 重挂到 QCoreApplication 后,在 ~QCoreApplication() 的 ~QObject::deleteChildren() 阶段析构。 此时 itemChange()/geometryChange() 钩子触发 scheduleLayout() → QTimer::start() → QObject::startTimer(),但 ~QCoreApplication() 体 已在基类析构体之前将 eventDispatcher 置空,导致以下告警:
"QObject::startTimer: Timers can only be used with threads started
with QThread"

Log: 修复DciIcon的startTimer警告

Influence:
1.DciIcon正确显示;
2.程序退出时,ListView、Repeater等容器中的DciIcon没有startTimer警告

PMS: TASK-392413

Summary by Sourcery

Bug Fixes:

  • Avoid QObject::startTimer warnings for DciIcon items when the event dispatcher is unavailable during application teardown.

@sourcery-ai

sourcery-ai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Adds a defensive check before scheduling the DQuickDciIconImage layout so that no QTimer is started when the event dispatcher is unavailable, preventing startTimer warnings during application teardown.

Sequence diagram for DQuickDciIconImage layout scheduling with event dispatcher check

sequenceDiagram
    participant ListViewDelegate
    participant DQuickDciIconImage
    participant DQuickDciIconImagePrivate
    participant QAbstractEventDispatcher
    participant QTimer

    ListViewDelegate->>DQuickDciIconImage: itemChange()/geometryChange()
    DQuickDciIconImage->>DQuickDciIconImagePrivate: scheduleLayout()
    DQuickDciIconImagePrivate->>QAbstractEventDispatcher: instance(DQuickDciIconImage.thread())
    alt dispatcher_available
        QAbstractEventDispatcher-->>DQuickDciIconImagePrivate: dispatcher
        DQuickDciIconImagePrivate->>QTimer: start()
    else dispatcher_unavailable
        QAbstractEventDispatcher-->>DQuickDciIconImagePrivate: null
        DQuickDciIconImagePrivate-->>DQuickDciIconImagePrivate: return without starting timer
    end
Loading

File-Level Changes

Change Details Files
Guard layout scheduling so no timer is started when the event dispatcher is unavailable (e.g., during QCoreApplication destruction).
  • Include QAbstractEventDispatcher to allow querying the current thread’s event dispatcher.
  • Before creating or starting the layout timer, check QAbstractEventDispatcher::instance(q->thread()) and return early if it is null.
  • Keep the existing lazy initialization of layoutTimer and its use unchanged, only gating the scheduling on dispatcher availability.
src/private/dquickdciiconimage.cpp

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

@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.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/private/dquickdciiconimage.cpp" line_range="222-223" />
<code_context>
 void DQuickDciIconImagePrivate::scheduleLayout()
 {
     Q_Q(DQuickDciIconImage);
+    if (Q_UNLIKELY(!QAbstractEventDispatcher::instance(q->thread())))
+        return;

     if (!layoutTimer) {
</code_context>
<issue_to_address>
**issue:** Consider whether silently returning when no event dispatcher exists is the desired behavior for `scheduleLayout`.

By returning early, layout updates are skipped whenever `q->thread()` lacks an event dispatcher. If this scenario is not expected, it may be preferable to assert, log, or fall back to `QAbstractEventDispatcher::instance()` on the current thread. If it is expected, consider adding a short comment explaining why suppressing layout here is acceptable to avoid confusion for future maintainers.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/private/dquickdciiconimage.cpp Outdated
Comment thread src/private/dquickdciiconimage.cpp Outdated
// ~QCoreApplication() nulls eventDispatcher before ~QObject::deleteChildren()
// destroys them, which may trigger itemChange/geometryChange hooks leading here.
// Same check as QObject::startTimer() internally, prevents the warning.
if (Q_UNLIKELY(!QAbstractEventDispatcher::instance(q->thread())))

@18202781743 18202781743 Aug 3, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

QCoreApplication析构的时候会触发Item的geometryChange的事件?

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码修复了组件在父项变更且无父项时仍继续执行布局调度导致的潜在崩溃问题,逻辑严谨且实现简洁。
逻辑正确且修复了潜在的空指针风险,无需扣分。

■ 【详细分析】

  • 1.语法逻辑完全正确✓

DQuickDciIconImage::itemChange 函数中,新增了对 ItemParentHasChanged 事件且 !parentItem() 的前置拦截。当组件父项被移除或销毁时,直接返回,避免执行后续的 d_func()->scheduleLayout(),有效防止了在脱离父节点后进行无效布局计算引发的空指针访问或无效状态更新。
潜在问题:无
建议:保持当前实现,逻辑清晰有效。

  • 2.代码质量良好✓

代码修改非常精简,仅增加了必要的条件判断,未引入冗余代码。遵循了原有的代码风格和缩进规范,可读性高。
潜在问题:无
建议:可考虑在 if 判断处增加简短注释,说明为何在无父项时需要直接返回,以便后续维护者快速理解意图。

  • 3.代码性能无性能问题✓

提前返回机制避免了在组件脱离父节点时触发不必要的 scheduleLayout 布局重算,减少了无意义的 CPU 消耗和事件处理开销,对性能有正向优化作用。
潜在问题:无
建议:无需额外优化。

  • 4.代码安全存在0个安全漏洞✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
本次代码修改未引入任何安全漏洞,反而通过修复潜在的空指针解引用问题提升了代码的健壮性和安全性,不存在外部输入注入或权限绕过等攻击面。

  • 建议:无需额外安全修复措施

■ 【改进建议代码示例】

void DQuickDciIconImage::itemChange(ItemChange change, const ItemChangeData &value)
{
    QQuickItem::itemChange(change, value);

    // 当父项变更且当前已无父项时,避免执行无效的布局调度,防止潜在崩溃
    if (change == ItemParentHasChanged && !parentItem()) {
        return;
    }

    if (change == ItemParentHasChanged || change == ItemDevicePixelRatioHasChanged || change == ItemSceneChange) {
        d_func()->scheduleLayout();
    }
}

… is unavailable

DQuickDciIconImage::scheduleLayout() may be invoked via itemChange()
or geometryChange() hooks during the destruction of ListView delegate
items reparented to QCoreApplication via QQmlDelegateModel. At that
point, ~QCoreApplication() has already set eventDispatcher to nullptr
, causing QObject::startTimer() to emit:
  "QObject::startTimer: Timers can only be used with threads started
   with QThread"

Log: Fix startTimer warning for DciIcon

Influence:
  1. DciIcon displays correctly;
  2. When the program exits, DciIcon in containers such as ListView and Repeater does not have a startTimer warning

fix(dtkdeclarative): 修复 eventDispatcher 不可用时 startTimer 告警

ListView delegate item 经 QQmlDelegateModel 重挂到 QCoreApplication
后,在 ~QCoreApplication() 的 ~QObject::deleteChildren() 阶段析构。
此时 itemChange()/geometryChange() 钩子触发 scheduleLayout() →
QTimer::start() → QObject::startTimer(),但 ~QCoreApplication() 体
已在基类析构体之前将 eventDispatcher 置空,导致以下告警:
  "QObject::startTimer: Timers can only be used with threads started
   with QThread"

Log: 修复DciIcon的startTimer警告

Influence:
  1.DciIcon正确显示;
  2.程序退出时,ListView、Repeater等容器中的DciIcon没有startTimer警告

PMS: TASK-392413
@52cyb

52cyb commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@source-ai review

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, 52cyb

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

@52cyb

52cyb commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

This pr force merged! (status: unstable)

@deepin-bot
deepin-bot Bot merged commit 3af03f9 into linuxdeepin:master Aug 3, 2026
20 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