Skip to content

[GUI Bug]: ProcessFragment.refresh_status 在后台线程直接操作 widget,偶发 segfault #558

Description

@2003Tim

错误描述(Bug Description)

1. 遇到的具体问题现象

gui/fragments/process.py 里的 ProcessFragment.refresh_status() 运行在一个 daemon 线程中,但它直接调用了 Qt widget 的方法(on_status.setTextlistWidget.clearlistWidget.addItems 等)。Qt 禁止在非 widget 所属线程(即非 GUI 线程)里操作 widget。这种访问在大多数平台上抛 RuntimeError: QObject::setText: Cannot send to a target object / QObject: Cannot create children for a parent that is in a different thread;在 Windows 上偶尔直接 segfault 进程,无 Python 异常。

2. 出现问题前的操作步骤

  1. 启动 BAAS GUI
  2. 进入「调度」页面(自动启动 daemon 线程 refresh_status,每 2 秒一次循环)
  3. GUI 线程正忙(用户切标签、滑动列表、切主题、布局重排等)时,下次 refresh_status 触发 widget 操作即可能崩

3. 问题是否稳定复现

非 100% 必现,是偶发。每次 refresh_status 循环都是一次"抽签",撞上 GUI 线程忙碌就有概率 segfault。Windows 上概率较高,Linux/macOS 上一般抛 RuntimeError 但仍属异常行为。

报错日志 / 截图 / 录屏(Related Log)

典型异常(Linux / macOS)

RuntimeError: QObject: Cannot create children for a parent that is in a different thread

QObject::setText: Cannot send to a target object

典型崩溃(Windows)

Process finished with exit code -1073740791 (0xC0000409)

无任何 Python traceback。

关键信息

  • 崩溃位置gui/fragments/process.pyrefresh_status() 方法(在线程 threading.Thread(target=self.refresh_status, daemon=True) 中运行)
  • 被违规访问的 widgetself.on_statusStrongBodyLabel)、self.listWidgetListWidget
  • 违规时机refresh_statuswhile True 循环每次末尾调用 time.sleep(2) 之前

补充信息(Additional Info)

尝试过的解决方法

  • ❌ 加 try / except RuntimeError 包住 widget 操作 —— 治标不治本,仍然有竞态,且 Linux 上抛异常会让状态变成"操作了一半"
  • ✅ 最终方案:数据走信号,widget 操作必须在 GUI 线程
    status_signal = pyqtSignal(str, list)
    ...
    # 后台线程:
    self.status_signal.emit(crt_task, task_list)
    time.sleep(2)
    
    # GUI 线程(自动 QueuedConnection):
    def _update_status_widgets(self, crt_task, task_list):
        self.on_status.setText(...)
        self.listWidget.clear()
        self.listWidget.addItems(...)

相关设置

  • 涉及文件:gui/fragments/process.py
  • 操作系统:所有平台,但 Windows 上表现最严重(直接 segfault)
  • 受影响版本:发现于 2026-08 月的当前 master / 各 PR 分支

已知 work-around

  • 无。refresh_status 一直在跑,无法禁用

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions