Skip to content

fix(editor): prevent main thread deadlock in selectTextInView - #494

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:master
Jul 30, 2026
Merged

fix(editor): prevent main thread deadlock in selectTextInView#494
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:master

Conversation

@pengfeixx

@pengfeixx pengfeixx commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Add re-entry guard to selectTextInView to break the self-excitation loop caused by setTextCursor triggering QInputMethod::update (fcitx5 async cursor query) and scrollbar/layout signals re-entering the function.

为 selectTextInView 添加重入守卫,阻断 setTextCursor 触发
QInputMethod::update(fcitx5 环境下异步回查光标矩形)及滚动条/布局
信号再次回调 selectTextInView 形成的自激振荡导致主线程死循环卡死。
同时 Release 构建禁用调试输出,调整默认主题资源路径。

Log: 修复全选时主线程死循环卡死问题
PMS: BUG-371465
Influence: 解决在 fcitx5 环境下执行视区内全选导致编辑器卡死的问题,同时优化 Release 构建输出与默认主题路径。

Summary by Sourcery

Prevent editor main thread deadlock when selecting text in view and adjust release build behavior.

Bug Fixes:

  • Add a re-entry guard flag to selectTextInView to prevent recursive calls that could deadlock the main thread during view-wide selection, especially under fcitx5 input method environments.

Enhancements:

  • Disable Qt debug output in Release builds to reduce unnecessary logging.
  • Adjust application resource handling by defining build-time defaults for the editor executable (including theme-related paths).

Build:

  • Conditionally define QT_NO_DEBUG_OUTPUT for the deepin-editor target in Release builds to suppress debug logs.

@sourcery-ai

sourcery-ai Bot commented Jul 30, 2026

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

Reviewer's Guide

Adds a re-entry guard around selectTextInView to prevent recursive re-entry and main-thread deadlock when performing select-all in fcitx5 environments, and adjusts build configuration to suppress debug output in Release builds and updates editor configuration defaults.

Sequence diagram for re-entry guard in selectTextInView

sequenceDiagram
    actor User
    participant TextEdit
    participant QInputMethod
    participant fcitx5
    participant ScrollBar
    participant Layout

    User->>TextEdit: selectTextInView
    opt [m_isSelectingInView is false]
        TextEdit->>TextEdit: selectTextInView
        TextEdit->>TextEdit: setTextCursor
        TextEdit->>QInputMethod: QInputMethod::update
        QInputMethod->>fcitx5: queryCursorRect
        fcitx5-->>ScrollBar: update scrollbar
        fcitx5-->>Layout: update layout
        ScrollBar->>TextEdit: slotValueChanged
        Layout->>TextEdit: resizeEvent
        TextEdit->>TextEdit: selectTextInView
    end
    opt [m_isSelectingInView is true]
        TextEdit-->>TextEdit: return (re-entry blocked)
    end
Loading

File-Level Changes

Change Details Files
Prevent recursive re-entry into selectTextInView that caused a self-excitation loop and main-thread deadlock when selecting all text in view.
  • Introduce m_isSelectingInView state flag as a re-entry guard for selectTextInView.
  • Check the guard flag at the start of selectTextInView and early-return when a selection-in-view operation is already in progress.
  • Set the guard flag to true before computing and applying the selection range and resetting the horizontal scrollbar, and clear it to false at the end of the function.
  • Document in comments how setTextCursor triggers QInputMethod updates and scrollbar/layout signals that previously re-entered selectTextInView in fcitx5 environments.
src/editor/dtextedit.cpp
src/editor/dtextedit.h
Tighten Release build behavior by disabling Qt debug output and adjusting resource configuration for the editor binary.
  • Add a conditional compile definition so that Release builds define QT_NO_DEBUG_OUTPUT for the deepin-editor target, suppressing qDebug output at runtime.
  • Ensure deepin-editor.qrc remains part of the executable target configuration while applying the new compile definition conditionally to Release builds.
src/CMakeLists.txt

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 left some high level feedback:

  • The re-entry guard in selectTextInView would be more robust if implemented with a scoped helper (e.g. a small RAII object or QScopedValueRollback<bool>) so future early returns or added error paths can't accidentally leave m_isSelectingInView stuck in the true state.
  • The if(CMAKE_BUILD_TYPE STREQUAL "Release") condition is fragile for multi-config generators (e.g. VS, Xcode); consider using generator expressions like $<CONFIG:Release> or a cache option to control QT_NO_DEBUG_OUTPUT instead.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The re-entry guard in `selectTextInView` would be more robust if implemented with a scoped helper (e.g. a small RAII object or `QScopedValueRollback<bool>`) so future early returns or added error paths can't accidentally leave `m_isSelectingInView` stuck in the `true` state.
- The `if(CMAKE_BUILD_TYPE STREQUAL "Release")` condition is fragile for multi-config generators (e.g. VS, Xcode); consider using generator expressions like `$<CONFIG:Release>` or a cache option to control `QT_NO_DEBUG_OUTPUT` instead.

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.

Add re-entry guard to selectTextInView to break the self-excitation
loop caused by setTextCursor triggering QInputMethod::update (fcitx5
async cursor query) and scrollbar/layout signals re-entering the function.

为 selectTextInView 添加重入守卫,阻断 setTextCursor 触发
QInputMethod::update(fcitx5 环境下异步回查光标矩形)及滚动条/布局
信号再次回调 selectTextInView 形成的自激振荡导致主线程死循环卡死。
同时 Release 构建禁用调试输出,调整默认主题资源路径。

Log: 修复全选时主线程死循环卡死问题
PMS: BUG-371465
Influence: 解决在 fcitx5 环境下执行视区内全选导致编辑器卡死的问题,同时优化 Release 构建输出与默认主题路径。
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:95分

■ 【总体评价】

代码有效解决了输入法回调和滚动条信号导致的死循环卡死问题,并在Release模式下优化了调试输出
逻辑正确且修复了严重的性能缺陷,代码注释清晰,无安全漏洞

■ 【详细分析】

  • 1.语法逻辑(基本正确)✓

TextEdit::selectTextInView() 函数中,通过在函数入口设置 m_isSelectingInView = true 并在函数末尾恢复为 false,成功阻断了由 setTextCursor 引发的信号回调重入。CMakeLists.txt 中的宏定义逻辑正确。
潜在问题:如果在 m_isSelectingInView = true;m_isSelectingInView = false; 之间发生异常或提前 return,会导致状态被永久锁定,但由于当前函数体内没有可能抛出异常的代码且无提前返回点,暂无实际风险。
建议:考虑使用 RAII 机制管理状态标志,以应对未来代码扩展可能引入的提前返回路径。

  • 2.代码质量(优秀)✓

代码修改具有良好的可读性,在 dtextedit.h 中添加了详细的注释说明重入守卫的目的和触发场景,帮助后续维护者理解上下文。CMake 修改符合规范。
潜在问题:无
建议:保持现有的注释习惯。

  • 3.代码性能(高效)✓

修复了由于自激振荡导致的主线程死循环卡死问题,极大地提升了程序在特定操作下的响应性能。Release 模式下禁用 qDebug 输出也减少了不必要的 I/O 开销。
潜在问题:无
建议:无

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

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
本次代码修改仅涉及重入控制和编译宏定义,未引入任何外部输入处理或敏感操作,不存在安全风险。

  • 建议:无需针对安全进行额外修复。

■ 【改进建议代码示例】

// 如果未来函数逻辑变得复杂,建议使用 RAII 管理状态
class ScopedFlag {
public:
    ScopedFlag(bool& flag) : m_flag(flag) { m_flag = true; }
    ~ScopedFlag() { m_flag = false; }
private:
    bool& m_flag;
};

void TextEdit::selectTextInView()
{
    qDebug() << "Selecting text in view";
    if (m_isSelectingInView) {
        qDebug() << "Selecting text in view skipped: already in progress";
        return;
    }
    ScopedFlag guard(m_isSelectingInView);

    int startPos = cursorForPosition(QPoint(0, 0)).position();
    QPoint endPoint = QPoint(this->viewport()->width(), this->viewport()->height());
    int endPos = cursorForPosition(endPoint).position();

    QTextCursor cursor = this->textCursor();
    cursor.setPosition(startPos);
    cursor.setPosition(startPos, QTextCursor::KeepAnchor);
    this->setTextCursor(cursor);
    this->horizontalScrollBar()->setValue(0);

    qDebug() << "Selecting text in view completed";
}

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, pengfeixx

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

@pengfeixx

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 1af1114 into linuxdeepin:master Jul 30, 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