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

3.5 KiB
Raw Blame History

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。