错误描述(Bug Description)
1. 遇到的具体问题现象
gui/fragments/process.py 里的 ProcessFragment.refresh_status() 运行在一个 daemon 线程中,但它直接调用了 Qt widget 的方法(on_status.setText、listWidget.clear、listWidget.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. 出现问题前的操作步骤
- 启动 BAAS GUI
- 进入「调度」页面(自动启动 daemon 线程
refresh_status,每 2 秒一次循环)
- 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.py 的 refresh_status() 方法(在线程 threading.Thread(target=self.refresh_status, daemon=True) 中运行)
- 被违规访问的 widget:
self.on_status(StrongBodyLabel)、self.listWidget(ListWidget)
- 违规时机:
refresh_status 的 while 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 一直在跑,无法禁用
错误描述(Bug Description)
1. 遇到的具体问题现象
gui/fragments/process.py里的ProcessFragment.refresh_status()运行在一个 daemon 线程中,但它直接调用了 Qt widget 的方法(on_status.setText、listWidget.clear、listWidget.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. 出现问题前的操作步骤
refresh_status,每 2 秒一次循环)refresh_status触发 widget 操作即可能崩3. 问题是否稳定复现
非 100% 必现,是偶发。每次
refresh_status循环都是一次"抽签",撞上 GUI 线程忙碌就有概率 segfault。Windows 上概率较高,Linux/macOS 上一般抛RuntimeError但仍属异常行为。报错日志 / 截图 / 录屏(Related Log)
典型异常(Linux / macOS)
或
典型崩溃(Windows)
无任何 Python traceback。
关键信息
gui/fragments/process.py的refresh_status()方法(在线程threading.Thread(target=self.refresh_status, daemon=True)中运行)self.on_status(StrongBodyLabel)、self.listWidget(ListWidget)refresh_status的while True循环每次末尾调用time.sleep(2)之前补充信息(Additional Info)
尝试过的解决方法
try / except RuntimeError包住 widget 操作 —— 治标不治本,仍然有竞态,且 Linux 上抛异常会让状态变成"操作了一半"Fixes #558)相关设置
gui/fragments/process.py已知 work-around
refresh_status一直在跑,无法禁用