Skip to content

[R2][回归] 定位系统 ConPTY 启动样本 resize 后仍回复旧尺寸 #145

Closed as not planned

Description

@JavaZeroo

已观察的失败

PR141默认工作流40742159646,attempt1,head 43883022883d382e3dd57bd627e9c735bafe58ca、实际checkout merge 9ecdba0,Windows job123006322929的CTest 52/53、285.94s。唯一失败为 test_watchdog_kills_only_owned_job 正式watchdog前的startup(normal),resized dimensions mismatch,不是watchdog工作负载超时或越界杀进程。

旧固定源probe先已收到TFREADY、80×24和精确UTF8 ECHO;session.resize(120,40)未抛错后仅发送一次SIZE。实际新增回复仍为 TFSIZE:80x24:END,原5秒等待未收到120×40。VT前缀另有CSI8;40;120t/旧画面重绘,不能据此证明child实际尺寸。样本ready1/echo1/resized0/descendant0;close后child code3221225786(0xC000013A),自然退出未知,read_error109、output596B、active_children_after0、forced reader/process均0,elapsed6052.71ms。具体调用先后、系统后台resize/child查询/流排序原因未知,尚不认定异步竞态。

本PR未改probe/Session/测试源。专用Qt/fixedConPTY验证和另一push运行不覆盖本system/legacy样本,未提交同HEAD重试。

原件artifact12839763555 ZIP SHA256 1d077810c6dc5f33eb5ba300c1888328ad2e8631117727fb57e391370e772756;LastTest.log145190B SHA256 7329a3b656223fb011cb8e7c28aa90b5c41599f395358be356a50e3b23dbe05f,本地保全。父项#38,相关#29/#143;不同source/backend结果分列。

有界接续

  • 固定旧输入、源码/二进制、实际system ConPTY/Windows身份、一个可证伪时序假设、样本数与停止条件;原5秒SIZE与watchdog8秒不变。
  • 记录resize调用前后、子程序独立CSBI采样、输入接收/nonce与原始VT的各阶段,不用请求值/返回S_OK/旧回显或resize VT作为childack。
  • 获得同类反例后单变量因果验证;任何采样/重查询协议变更明确为新源码与诊断,不丢弃旧尺寸或把新成功回填旧根因。未复现只记录该批实际结果。
  • 原自然退出/清理边界与所有原件保留;修复复验实际完整行为。当前#143正式fixedConPTY动态尺寸工作独立推进,不自动修复本system探针。

不运行WindTerm、不修改个人桌面,不延长期限/删预期/重跑取绿。本项和#38/#35/R2保持开放。

Activity

  1. added
    ready-for-agent范围明确且真实阻塞已解除,可开始实施
    research有明确问题与出口的证据调查
    on Oct 28, 2026
  2. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    PR168 的首次 push 回归新增同类观察:run40814207316、Windows job123251361984,60/61、299.34s;唯一 conpty 失败在 close 第三轮的 resize reply gate,尚未进入 TREE/SPAM。ready/echo=1、resized=0;目标请求120×40,但596B完整VT仅含三次80×24回复和resize VT。CLI1、非外层timeout、Job0/12/0,不能称已建忙碌树的关闭回收失败。

    该596B与本issue旧PR141 startup失败捕获逐字节一致,SHA256 c63fc584c75f7be84b1f4a6a995841ade67af9931c43eaae44f0375e0f56a085;相关六个ConPTY源文件未变,只支持同类观察,根因仍未知。失败artifact12871348874为4797707B/SHA 4cb48a8827605f7facf4ec294b99bd014f81cff0d3514ecf4e6135a369a0c4f8,原件及成员验和留私有;该artifact不含EXE,逐运行EXE和系统DLL身份未知。

    同head的PR运行 Windows61/61、277.85s;其checkout29c58f4与push fe72d897的tree相同,但结果独立保留,不覆盖红例,未rerun/retest。本次#73相关断言及#160 watchdog均通过。R2与本issue继续开放。

  3. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    有界接续切片:把“resize 返回后立即排入 SIZE 查询”这一时序放大采样,判断它是否足以解释本 issue 的旧尺寸回复。

    方法(不改原探针/oracle/5s 等待):新增 conpty_resize_reply_probe + resize_reply_run.py,客户端报告自己的 buffer(dwSize) 与 window(srWindow),回复带独立 tag;raw 模式同一会话交替 120×40/80×24 各 200 轮,startup 模式每次全新会话复刻 ready→SIZE→ECHO→resize(120×40)→SIZE。运行于 workflow_dispatch 的 windows-2025-resize-reply job(build.yml 同一 hosted 镜像),只断言结构完整性,陈旧计数作为证据记录。

    结果(结果与身份、validation.json):

    环境 模式 样本 陈旧回复 buffer/window 分歧
    Windows 11 26200(本机) raw / startup 200 / 100 0 0
    hosted Windows Server 2025(run 40841303342) raw 1000 0 0
    hosted Windows Server 2025(run 40841934880) raw / startup 1000 / 500 0 0
    • 2800 样本全部返回请求尺寸;resize VT 100% 先于回复;回复中位 8.7–16.1 ms、最大 64.7 ms,远低于原 5 秒等待,说明失败样本不是“等得不够久”。
    • 若陈旧来自“window 已更新、buffer 未更新”,应记录到分歧;实际为 0。

    结论与边界:否定“resize 后立即查询存在必然时序竞态”这一假设;本 issue 的两条 CI 失败(PR141 40742159646、PR168 push 40814207316,596B 逐字节一致)仍是真实失败,根因未知,#145/#38 状态不变。未覆盖:原探针在完整 ctest 上下文中的运行、hosted 运行器镜像/宿主差异、以及“每次运行首条会话”这类稀有例外。

    下一步(有界):在同一 hosted 运行器上跑原探针本身的重复批次,确认 clone 与原 oracle 的失败率是否一致;若两者皆为零,优先固定首个会话/首条 resize 的宿主状态,而不是继续放大同一时序样本量。

  4. added a commit that references this issue on Oct 29, 2026
  5. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    诊断切片已合入 main(PR #171,dc666ef):conpty_resize_reply_probe + dispatch-only 的 windows-2025-resize-reply 作业 + 固定结果。结论仍是 2800 样本无陈旧回复(hosted windows-2025:1000 交替 resize + 500 全新会话),否定“resize 后立即查询必然竞态”。本 issue 保持开放:原两条 CI 失败(PR141 40742159646、PR168 push 40814207316)仍是真实失败、根因未知;下一步按 bounded 计划在同宿主跑原探针的重复批次,并优先固定“首个会话/首条 resize”的宿主状态。

  6. JavaZeroo commented on Oct 29, 2026

    @JavaZeroo
    OwnerAuthor

    第二片有界接续:重复原探针本身,以及“先跑控制台密集测试再采样”,用来判断旧尺寸回复是否与作业上下文有关。

    方法:新增 experiments/conpty/repeat_run.py,每迭代复用既有 run.execute()(自有 Job、GO 门、原 5 秒等待、原断言),逐次保留独立结果;两个 dispatch-only 作业 —— 隔离重复 40×4、先在 conpty_ctrl_c(5.31s)/conpty_margin(0.31s) 通过之后采样 20×4。

    结果:

    条件 run 样本 resize 旧尺寸 其它红色
    isolated(hosted windows-2025) 40847785625 160 0 0
    控制台测试之后 40849464556 80 0 1
    对照:克隆探针(合入自 PR #171) 40841303342 / 40841934880 2800 0 0

    唯一红色不是本 issue 的症状:iteration 10 的 normal repeat 1,resized=1、最终 VT 为 TFSIZE:120x40:END、child exit 37、608B 完整;失败判据是 steady_resources=false——会话结束后线程 4→6、resource_settle_ms=1011.02 超过 1 秒结算窗口。这属于 #38 族的稳态夹具边界(首次初始化只对 startup 豁免),不并入 #145 根因,也不说明 resize 机制有问题。

    结论:原样本在“隔离”和“轻度前置”两种上下文下都未复现旧尺寸回复;根因仍未知。本片只缩小假设空间,不关闭 #145。

    保留的反例:分支上“先跑完整 ctest 再采样”的作业(run 40848143873)因该 dispatch 作业缺少 build.yml 的夹具准备,在 benchmark_tools/differential/workflow_*/shell 失败,未进入采样阶段——这是“作业环境不等价”,不能当作采样结果。

    下一步(有界):要真正复刻 build.yml 的上下文,需要复制其准备步骤(hosted shell/benchmark 夹具),或改为在 build.yml 的 job 内直接插入一次重复采样;两条都会改动常规 CI,需先评估成本。否则建议把 #145 当作“低频不可复现”,由 #38 的回归策略按已记录失败处理,不再无界重复。

  7. added a commit that references this issue on Oct 29, 2026
  8. JavaZeroo commented on Oct 30, 2026

    @JavaZeroo
    OwnerAuthor

    现状记录:连续 13 轮全绿,旧尺寸回复仍 0 复现

    • 本项此前的有界采样:2800 次 resize 回复采样、0 次旧尺寸回复;
    • 近期 main 上的扩展重复作业(text_actions|selection_context|shell,5 次重复)已连续 13 轮全绿,累计约 260 次执行,仍没有出现"resize 后回复旧尺寸";
    • 期间新增的诊断(输出心跳含 pid/child_signaled/exit_code、几何切换记录、失败路径 readiness)都能在下一次同类命中时提供更细的边界。

    保持开放的理由

    本项验收要求"获得同类反例后单变量因果验证";目前只有大样本未复现,没有同类反例,因此不改写为"已修复",也不关闭。

    下一假设

    若再次出现,优先检查:resize 请求与 SIZE 回复之间的时序是否被 ConPTY 的尾部队列重排(与 #194 的重绘错位同一类窗口),用现有 termforge-resize-trace-v1 与回复时刻对照即可判定。

  9. JavaZeroo commented on Oct 30, 2026

    @JavaZeroo
    OwnerAuthor

    对 2800 样本记录的核对:数字可复算,身份可复算,结论口径需收紧

    位置更正:该切片实际在 experiments/conpty/results/2026-10-29-resize-reply-r145/(research/ui/results/ 下没有该目录)。同族还有 experiments/conpty/results/2026-10-29-probe-repeat-r145/。

    1. 记录项逐条复算

    记录项 记录值 复算 结论
    样本总数 2800 2000(hosted raw) + 500(hosted startup) + 200(local raw) + 100(local startup) ✅ 自洽(validation.json:15-62)
    陈旧回复 / buffer-window 分歧 0 / 0 与 replies_with_resize_vt_before_reply="2800/2800" 一致,各环境表逐行相加合规 ✅ 自洽
    中位回复耗时 8.7–16.1 ms resize_to_reply_us_median_range=[8686.5,16072] µs = 8.69–16.07 ms ✅ 一致
    最大耗时 64.7 ms resize_to_reply_us_max=64735 µs ✅ 一致
    与原探针 5 秒等待的关系 远低于 64735 µs vs original_probe_wait_ms=5000 ✅ 一致
    源身份 4 项 source_sha256 在 validation.json:4 记录的 commit d66f9f3 上按 CRLF 检出形式重算:probe.cpp 03efd353…、run.py e3ff4b07…、session.hpp c85872fd…、backend.hpp c64309b7… 4/4 逐字节相同 ✅ 身份可复算(本仓库 core.autocrlf=true,cmp/hpp 的 LF blob 哈希不同属检出形式差异,不是内容漂移)

    2. 引用时必须保留的两条口径

    事实 依据 影响
    陈旧计数是记录值,不是断言门槛 resize_reply_run.py:29-45 仅 summarize() 统计 stale_buffer/stale_window/disagreement 并写入证据,不设 gate 不能写成"断言通过";只能说"2800/2800 未观测到陈旧回复"
    探针报告的是客户端自己的 CSBI resize_reply_probe.cpp:112-116 读 GetConsoleScreenBufferInfo,同时给 dwSize 与 srWindow;回复带独立 tag(:134/:149) 这正是 issue 要求的"子程序独立 CSBI 采样、不用请求值/S_OK/旧回显"的形态,但它只覆盖 resize 后立即查询这一个时序

    结论:记录本身没有发现算术或身份矛盾;它排除的假设范围应严格写作"resize 成功后立即排入 SIZE 查询"这一孤立时序,而不是"任何时序竞态"。

    3. issue 要求的下一次观测只有一个

    在失败真正发生的上下文里(build.yml 的完整 ctest 顺序与并发、同一 runner 镜像),对该 job 的第一个会话 / 第一条 resize记录 resize 调用前后各阶段时序,并对 child 做独立 CSBI 采样。

    理由(避免重复已做完的样本放大):

    已完成的放大 样本 陈旧回复
    克隆探针(本切片) 2800 0
    原探针隔离重复(2026-10-29-probe-repeat-r145,run 40847785625) 160 0
    控制台密集测试后采样(run 40849464556) 80 0

    三种条件都为 0,唯一尚未建模的变量就是宿主/镜像/并发顺序——即本切片 README 的"下一步 2"。(README 的"下一步 1:在同 hosted 跑原探针本身"已由 2026-10-29-probe-repeat-r145 完成,不应再作为下一步重复。)

    边界

  10. JavaZeroo commented on Oct 31, 2026

    @JavaZeroo
    OwnerAuthor

    又一批量化结果:1500 轮 resize,三项异常计数全为 0

    数据来源:run 41198898623 的 conpty-resize-reply-r145 artifact(10 个 resize-reply.json:6 个 session + 4 个 startup 配置)。

    项 合计
    文件数 10(全部 status=passed)
    请求轮次 1500
    stale_buffer 0
    stale_window 0
    buffer_window_disagreement 0
    resize_vt_before_reply 1000

    延时(探针自带、仅作分布参考、非性能声明):

    指标 值
    resize_to_reply_us 中位数(10 个文件的中位数再平均) ≈13.8 ms
    单次最大值 23.6 ms

    对本项的意义

    本项要的是同类反例:一次实际观测到 resize 之后仍回复旧尺寸(TFSIZE:80x24:END)的样本。本批 1500 轮里:

    • 没有任何一次陈旧回复;
    • 也没有缓冲区与窗口尺寸不一致的样本。

    即:这批仍未复现,与之前的结论一致。

    边界

    本项按自身验收文字保持开放。

  11. JavaZeroo commented on Nov 1, 2026

    @JavaZeroo
    OwnerAuthor

    按「不死磕」原则关闭:系统 ConPTY resize 后仍回复旧尺寸

    关闭理由

    用户明确「可以接受不完美、不需要一直死磕一个问题」。本项属于批次内不可复现、诊断已就位的一类,因此按此原则关闭。

    本项已有的证据

    run 41198898623 的 conpty-resize-reply-r145 artifact:10 个配置、1500 轮,stale_buffer=0、stale_window=0、buffer_window_disagreement=0;resize_to_reply_us 中位约 13.8 ms、最大 23.6 ms(探针自身计时,非性能声明)。

    已就位的诊断(再次命中时可立即判读)

    观测 位置
    陈旧缓冲/窗口与不一致计数 resize-reply.json 的 stale_buffer/stale_window/buffer_window_disagreement
    每轮延时分布 同文件 resize_to_send_us/resize_to_reply_us

    关闭时的真实状态

    本项不是根因修复。原始失败记录仍保留,未被新批次覆盖。

    重开条件

    若同类失败再次出现,凭上述诊断字段可直接判读,恢复本项即可,无需重做本轮探索。

  12. removed
    ready-for-agent范围明确且真实阻塞已解除,可开始实施
    on Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    research有明确问题与出口的证据调查

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions