Files
StellarX-kaifa/开发记录/BUG/BUG-20261004-0001-EasyX原生窗口销毁后宿主事件循环未退出.md

58 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BUG-20261004-0001
> 适用场景:记录问题本身,不展开完整修复方案。修复内容写入对应的 Fix 文档。
## 基本信息
- ID: BUG-20261004-0001
- 标题: EasyX 原生窗口销毁后宿主事件循环未退出
- 状态:已修复
- 严重性:S2
- 优先级:P1
- 模块: Window / Dialog / EasyX 事件循环 / 输入探测
- 版本 / 分支: `master`,生产修复基线 `c0eca1d`
- 环境: Windows / EasyX / Visual Studio 2022 / Debug x64
- 发现人: 用户与 Codex 协作探测
- 关联 Fix ID: Fix-BUG-20261004-0001
## 问题描述
- 现象: 真实微软拼音探测完成后关闭 EasyX 窗口,窗口从桌面消失,但 `StellarX.UiFixture.exe` 和调用它的人工探测脚本继续运行,脚本无法进入隐私安全摘要阶段。
- 影响范围: `Window::runEventLoop()` 及 `Dialog::Show()` 自建轮询循环;当 EasyX 内部窗口线程完成原生 HWND 销毁,而宿主 `peekmessage` 线程没有收到对应 `WM_CLOSE` 时均可能挂住。
- 期望结果: 原生窗口生命周期结束后,普通事件循环和模态事件循环都应在安全点自行退出,探测脚本继续分析已落盘日志。
- 实际结果: 事件循环仅以宿主侧 `WM_CLOSE` 为退出条件;窗口已经销毁时仍继续轮询。
## 复现信息
- 前置条件: 构建开启 `StellarXInputProbe` 的 `StellarX.UiFixture`,通过 `scripts/run-input-probe-manual.ps1 -ImeName MicrosoftPinyin` 启动。
- 复现步骤:
1. 按人工清单完成微软拼音提交、重复字符、取消、候选选择和中英文切换操作。
2. 关闭 EasyX 原生窗口。
3. 观察窗口消失后脚本仍未输出摘要,fixture 进程仍存在。
- 复现概率:修复前真实人工会话稳定复现
- 最小复现 Demo:`StellarX.UiFixture.exe input-probe <result-dir>`;普通循环和真实 `MessageBox::showModal()` 均可构造关闭回归。
- 证据:
- 会话目录:`TestResults/InputProbe/manual-20261004-194521-908-MicrosoftPinyin`。
- 日志观察到 `WM_CLOSE -> WM_DESTROY -> WM_NCDESTROY`,但宿主 EasyX 消息批次没有取得 `WM_CLOSE`。
- 关闭后原挂起进程 PID 32948 仍存在,结束该进程后脚本才能退出。
## 初步分析
- 疑似位置: `Window::runEventLoop()`、`Dialog::Show()` 与 `Window::WndProcThunk()` 之间的原生窗口生命周期同步。
- 触发条件: EasyX 的 HWND/WndProc 所在线程与调用 `peekmessage` 的宿主线程不同,且原生关闭消息没有映射为宿主侧 `EX_WINDOW/WM_CLOSE`。
- 相关线索:
- 独立 `EasyX.ThreadProbe` 已确认双线程是 EasyX 固有模型,不是 UiFixture 夹具造成。
- 旧事件循环只在 `peekmessage` 返回的消息为 `WM_CLOSE` 时停止。
- HWND 已失效后继续尺寸轮询或绘制还会扩大为失效句柄访问风险。
- 最近相关改动: 阶段 0A 探测器首次把 WndProc 与宿主批次放进同一时间线,暴露了此前被单线程假设遮蔽的生命周期缺口。
## 跟踪信息
- 首次发现时间: 2026-10-04
- 最后更新时间: 2026-10-05
- 修复版本: `c0eca1d`(`fix: 原生窗口销毁后宿主事件循环未退出`)
- 验证版本: Debug x64;单元测试 15/15;普通与模态原生关闭自动回归通过
- 备注: EasyX `EX_SHOWCONSOLE` fixture 由 `Start-Process` 托管时,原生关闭可能返回 `0xC000013A`;该状态与“窗口关闭后进程仍挂住”是不同问题,回归以有界时间内自行退出为核心断言。阶段 0A 诊断实现与线程归属复现见 `c218c25`。