修复 task_queue 信号 lambda connect 跨线程 GUI 调用导致的 access violation
faulthandler 抓到 7 个 Windows access violation 栈, 全部归到同一根因: worker_ref.finished/error/progress (QThread 信号) 和 task_completed 用 lambda connect 时, lambda 没有 QObject thread affinity, Qt 默认按 DirectConnection 处理, 导致 lambda 在 worker 线程同步执行, 链路尽头 动主线程 GUI (refresh_history / _update_summary / display_image) → C++ 层 access violation。 Windows 表现为 fatal exception: access violation, 用户感知"crash"; macOS 触发后多被 SIGKILL 静默闪退, faulthandler 拦不到, 这就是最近 "Mac 仍闪退"剩余尾巴的同源问题。 修复: 5 处 lambda connect 全部显式 Qt.QueuedConnection, 强制 handler 进 receiver 主线程 event loop 排队, 彻底消除跨线程 GUI 调用。
Showing
2 changed files
with
17 additions
and
5 deletions
| ... | @@ -3092,9 +3092,12 @@ class ImageGeneratorWindow(QMainWindow): | ... | @@ -3092,9 +3092,12 @@ class ImageGeneratorWindow(QMainWindow): |
| 3092 | ) | 3092 | ) |
| 3093 | 3093 | ||
| 3094 | # Connect to task completion signal | 3094 | # Connect to task completion signal |
| 3095 | # 🔒 QueuedConnection: lambda 没有 QObject receiver, 不强制排队的话会被当 DirectConnection, | ||
| 3096 | # 在发射方所在线程同步执行 → 跨线程动 GUI → access violation (Win) / 静默闪退 (Mac) | ||
| 3095 | self.task_manager.task_completed.connect( | 3097 | self.task_manager.task_completed.connect( |
| 3096 | lambda tid, img, p, refs, ar, size, model: | 3098 | lambda tid, img, p, refs, ar, size, model: |
| 3097 | self._on_my_task_completed(task_id, tid, img, p, refs, ar, size, model) | 3099 | self._on_my_task_completed(task_id, tid, img, p, refs, ar, size, model), |
| 3100 | Qt.QueuedConnection, | ||
| 3098 | ) | 3101 | ) |
| 3099 | 3102 | ||
| 3100 | # Update UI | 3103 | # Update UI |
| ... | @@ -4681,9 +4684,11 @@ class StyleDesignerTab(QWidget): | ... | @@ -4681,9 +4684,11 @@ class StyleDesignerTab(QWidget): |
| 4681 | ) | 4684 | ) |
| 4682 | 4685 | ||
| 4683 | # Connect to task completion signal | 4686 | # Connect to task completion signal |
| 4687 | # 🔒 QueuedConnection 同上, 防 lambda 在 worker 线程被 DirectConnection 同步触发 | ||
| 4684 | self.parent_window.task_manager.task_completed.connect( | 4688 | self.parent_window.task_manager.task_completed.connect( |
| 4685 | lambda tid, img, p, refs, ar, size, mdl: | 4689 | lambda tid, img, p, refs, ar, size, mdl: |
| 4686 | self._on_my_task_completed(task_id, tid, img, p, refs, ar, size, mdl) | 4690 | self._on_my_task_completed(task_id, tid, img, p, refs, ar, size, mdl), |
| 4691 | Qt.QueuedConnection, | ||
| 4687 | ) | 4692 | ) |
| 4688 | 4693 | ||
| 4689 | # Update UI | 4694 | # Update UI | ... | ... |
| ... | @@ -206,17 +206,24 @@ class TaskQueueManager(QObject): | ... | @@ -206,17 +206,24 @@ class TaskQueueManager(QObject): |
| 206 | 206 | ||
| 207 | # 绑定信号;用 worker 局部引用捕获 finish_reason,避免后续 _current_worker 被替换 | 207 | # 绑定信号;用 worker 局部引用捕获 finish_reason,避免后续 _current_worker 被替换 |
| 208 | worker_ref = self._current_worker | 208 | worker_ref = self._current_worker |
| 209 | # 🔒 必须 QueuedConnection: worker_ref 是 QThread, finished/error/progress 从 worker 线程发出。 | ||
| 210 | # lambda 没有 QObject thread affinity, 默认会被当成 DirectConnection 在 worker 线程同步执行, | ||
| 211 | # 链路尽头会动主线程 GUI (refresh_history / _update_summary), C++ 层 access violation。 | ||
| 212 | # Windows 表现为 fatal exception, macOS 表现为静默 SIGKILL 闪退。 | ||
| 209 | worker_ref.finished.connect( | 213 | worker_ref.finished.connect( |
| 210 | lambda img_bytes, prompt, ref_imgs, ar, size, model: | 214 | lambda img_bytes, prompt, ref_imgs, ar, size, model: |
| 211 | self._on_task_completed(task_id, img_bytes, prompt, ref_imgs, ar, size, model, | 215 | self._on_task_completed(task_id, img_bytes, prompt, ref_imgs, ar, size, model, |
| 212 | getattr(worker_ref, 'finish_reason', None)) | 216 | getattr(worker_ref, 'finish_reason', None)), |
| 217 | Qt.QueuedConnection, | ||
| 213 | ) | 218 | ) |
| 214 | worker_ref.error.connect( | 219 | worker_ref.error.connect( |
| 215 | lambda error: self._on_task_failed(task_id, error, | 220 | lambda error: self._on_task_failed(task_id, error, |
| 216 | getattr(worker_ref, 'finish_reason', None)) | 221 | getattr(worker_ref, 'finish_reason', None)), |
| 222 | Qt.QueuedConnection, | ||
| 217 | ) | 223 | ) |
| 218 | worker_ref.progress.connect( | 224 | worker_ref.progress.connect( |
| 219 | lambda status: self.task_progress.emit(task_id, 0.5, status) | 225 | lambda status: self.task_progress.emit(task_id, 0.5, status), |
| 226 | Qt.QueuedConnection, | ||
| 220 | ) | 227 | ) |
| 221 | 228 | ||
| 222 | self.task_started.emit(task_id) | 229 | self.task_started.emit(task_id) | ... | ... |
-
Please register or sign in to post a comment