fix(provider): 构建期发心跳,避免冷机首次被 d2x 活性超时误杀 - #88
Merged
Conversation
有反馈说 d2x checker 在 Windows 10 上会卡住。除了已修的 cmd.exe 重定向,还有
一条与平台无关、冷机才撞得到的:
mcpp test --message-format json 在整个构建期一个字节都不产出。
这是实测结论,不是推断 —— 带不带 -q 都一样:stdout 只有末尾那两行 JSON,
stderr 全空(机器可读模式把人读输出整个收编进 JSON 了)。所以从 d2x 的视角看,
Provider 从 stage("compile") 之后就彻底沉默,直到构建结束。
冷机第一次要在这段沉默里备工具链与 std 模块。一旦超过 d2x 的活性超时
(provider_idle_timeout,默认 120s),正常构建会被当成挂死而终止;更糟的是学习者
改一次文件就重试一次、每次都在同一处被杀,表现为「怎么改都过不去」——
与「卡住」难以区分。
做法:capture_stdout 把读取交给工作线程(fgets 是阻塞的,单线程在沉默期根本回
不到我们手里),主线程每 20s 发一条 output 事件。一举两得:持续喂活 d2x 的计时
器,并让学习者看见首次构建正在进行,而不是对着黑屏干等。
比单纯调大 120s 阈值更对症 —— 阈值调多大都是猜,心跳把「有进展」变成可观测
事实。runner 保持协议无关:回调由 main.cpp 注入,发射逻辑不下沉。
验证:
- 心跳会发 —— 临时把间隔设为 0 跑一次,确认 output 事件出现(改回 20s 后
热构建 0 条,不打扰正常路径)
- 无回归 —— d2x/buildtools/tests/e2e.sh zh:协议冒烟 52 练习 ✓ /
pristine 全部保持未通过 ✓ / 52/52 参考答案全部通过 ✓
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
接着 #87 继续排查「d2x checker 在 Windows 10 上卡住」的反馈。#87 修的是 cmd.exe
的
/dev/null重定向(那条更早、更普遍);这条与平台无关,冷机第一次才撞得到。实测结论:构建期完全静默
不是推断,是跑出来的 —— 带不带
-q都一样:stdout 只有末尾那两行 JSON,stderr 全空(机器可读模式把人读输出整个收编进 JSON 了)。
所以从 d2x 的视角看,Provider 从
stage("compile")之后就彻底沉默,直到构建结束:为什么这会表现成「卡住」
冷机第一次要在这段沉默里备工具链与 std 模块。一旦超过 d2x 的活性超时
(
provider_idle_timeout,默认 120s 且默认开启),正常构建会被当成挂死而终止。更糟的是它不是「报错一次就完了」:checker 判 fail 后驻留等文件变更,学习者改一次
文件就重试一次、每次都在同一处被杀 —— 循环无解,与「卡住」难以区分。
做法:心跳,而不是调大阈值
capture_stdout把读取交给工作线程(fgets是阻塞的,单线程在沉默期根本回不到我们手里),主线程每 20s 发一条
output事件。一举两得:比单纯把 120s 调大更对症:阈值调多大都是猜,心跳把「有进展」变成可观测事实。
runner保持协议无关 —— 回调由main.cpp注入,发射逻辑不下沉到 runner。不传回调时完全不介入(默认参数为空,直接 join,无轮询)。
验证
心跳确实会发:临时把间隔设成 0 跑一次,确认
output事件出现;改回 20s 后热构建 0 条 —— 不打扰正常路径(热构建 60ms,远不到 20s)
无回归:
bash d2x/buildtools/tests/e2e.sh zh未覆盖
本机无法低成本复现真正的冷启动 —— 昂贵的部分在全局
~/.mcpp/build-cache/,清工程的
target/只会得到 60ms 的重建。所以「超过 120s 的沉默」这一前提是从「构建期零输出」+「冷机需备工具链与 std 模块」推出来的,心跳逻辑本身则是实测过的。