Repository navigation
Replies: 3 comments
|
更正(发帖人自纠):上面两次「宿主静默消失」的 ESRCH,不是自崩,是用户手动 taskkill 掉的——宿主在 shell 工具执行期间会长时间无响应(用户原话:「卡很久都不可能响应」),等不及主动结束进程。 所以本贴的真实标题应是:shell 工具输出超长单行时,宿主进入长时间无响应,而不是进程自崩。
|
|
三个问题都能从「为什么是静默」这个角度回答,而且你的两个假说可以合并成一个:不是 OOM,是无 dump 的 abort。 为什么没有任何痕迹V8 的 fatal abort 走 这意味着一件事:你缺的不是"崩溃前落盘",而是 stderr 从来就没接到文件上。你自己已经指出来了( 你的三个问题1. 宿主有没有崩溃前落盘机制? 没有面向用户的。但有两个成本极低的替代,第 1 条现在就能做: dsh web > "%LOCALAPPDATA%\dsh\host-out.log" 2> "%LOCALAPPDATA%\dsh\host-err.log"V8 在 abort 前会把 第二条(值得作为建议提):进程退出时由拉起着写一行 marker,即你提议的 2. shell 输出能否按字节硬截断? 能,而且这是标准做法。现在的 按字节截断的正确形状是在流式读取时累积字节数,超过阈值直接落 spill 并标记: 关键是标记必须显式出现,否则调用方拿到的是"看起来完整但其实是片段"的输出,比截断本身更危险。 3. 加"超长行保护"值不值? 值得,但阈值不要照抄 1 MB。你两次现场的共同点是 minified 单行 —— 这类文件单行常在 200 KB 到数 MB。建议两个参数:
这样普通日志(无论多少行)完全不受影响,只有病态单行才会走 spill。 一个能确认假说的实验在修之前就能做,成本约 2 分钟: # 造一个已知大小的超长单行
$f = "$env:TEMP\oneline.txt"
[IO.File]::WriteAllText($f, ("A" * 5MB))
# 在 DSH 里对 $f 执行一次 grep,同时用独立进程采样 RSS如果 RSS 在 grep 期间出现一次陡增后宿主消失,你的"单次大分配"假说就确认了。如果 RSS 平稳地涨到几 GB 才死,那是累积 OOM,方向完全不同。 顺带说明: 建议的报告结构把「证据」和「假说」分开写,并明确标注:
这样接手的人不会把未验证的假说当作结论去改错地方。 |
|
结案更新:假说全部被推翻——不是 OOM、不是 abort、也不是超长单行。 先谢这两条分析,推理本身是对的(无 WER 确实指向 abort 类路径、字节级截断确实是正确形状)。但我今天拿到了决定性证据,结论跟你我此前的方向都不一样。 决定性证据给宿主加上 全部来自第三方插件 关键读数:
也就是:"超长单行 / 单次大分配"这条线可以整条划掉了。我此前也顺着它走,错了。 真正的根因该插件 /^cd\s+((?:[^\s'";&|<>`$()#]+|'[^'\n\r]*'|"[^"\n\r]*")+)\s*&&\s*(.+)$/
所以:进程既没崩也没 OOM,是主线程被一条正则锁死——UI 自然全黑、HTTP 探针全超时、工具结果没能落盘。你看到的"没有 stderr"不是因为 stderr 没接上,而是根本没有终止事件可写(最后是用户 这对你三条建议意味着什么
真正该加进宿主的那一条每个工具结果的同步处理要有时间预算,超时即熔断(跳过处理、保留原文、记一行 理由:插件生态里"fail-open"几乎都只包 如果 DSH 侧愿意,最小可行版是: 我已按此把标题与结论更新,并附了抓栈方法( |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
原始报告(2026-11-15 上午)— 保留,结论已被下方更新推翻
现象:
taskkill),代理侧因此看到kill-0 probe failed (ESRCH)。Get-WinEvent Application无条目、WER\ReportArchive|Queue无 11-15 目录、无 stderr(当时启动命令未重定向)。证据缺口(当时):拿不到"卡住时"的栈——宿主没带
--inspect,只能等它退出看退出码。更新(同日 13:30):已定位,假说全部推翻
假说①②都不成立:不是 OOM、不是 abort、也不是超长单行。
决定性证据
给宿主加
--inspect=127.0.0.1:9229,用一个脱离宿主进程树的看门狗每 10 s 探测http://127.0.0.1:3080/dgh-dashboard/,连续 2 次超时即用 CDPDebugger.pause抓栈。三次连续抓取,6 帧完全一致:全部来自第三方插件
dsh-tool-result-trimmer@2.8.0——它挂在tools/post-execute上,每个工具结果都同步跑一遍。关键读数:
Debugger.pause延迟 101 ms:主线程在跑 JS,不是阻塞在系统调用,也不是卡在分配;alive=1、RSS 平稳在 577–795 MB:没有任何"死前峰值";cd ~/…/src/mailbox 2>/dev/null && sed -n '50,75p' tools.ts && grep -rn "args?.from" . | head -5。⇒ "超长单行 / 单次大分配"这条线可以整条划掉。进程既没崩也没 OOM,是主线程被一条正则锁死:UI 全黑、HTTP 探针全超时、工具结果没能落盘。没有 stderr 不是因为 stderr 没接上,而是根本没有终止事件可写(最后是用户
taskkill)。根因
该插件
commandContext()里一条嵌套量词正则:/^cd\s+((?:[^\s'";&|<>`$()#]+|'[^'\n\r]*'|"[^"\n\r]*")+)\s*&&\s*(.+)$/cd <较长目标> 2>/dev/null && …这种形状(目标后面不是&&)会让它失败后指数回溯。离线复跑同一函数:目标 16 字符 168 ms、20 字符 340 ms、24 字符 3 548 ms、39 字符 >10 s(被timeout杀掉),每 +4 字符约 ×8–10。上游已报:
Jaylor-Wang/dsh-tool-result-trimmer#1(崩因)、#2(审计:20+ 次卡死、语义 reducer 实测命中 0 次、宣传范围大于实现)。对既有加固建议的影响
真正该加进宿主的一条
每个工具结果的同步处理要有时间预算,超时即熔断(跳过处理、保留原文、记
reducer-slow)。插件生态里的 "fail-open" 几乎都只包
try/catch,而正则卡死不抛异常,只是永不返回。最小可行版:tools/post-execute的每个 handler 用AbortSignal+ N ms 预算包裹,超时即放弃该 handler 的输出并原样透传——任何一个第三方 reducer 写坏都不会再拖垮整个宿主。可复用的取证方法
--inspect=127.0.0.1:9229启动宿主 → 外部看门狗探测 UI 端点(2 次超时判定)→Debugger.pause取callFrames+Runtime.getHeapUsage→ 落 JSON。5 分钟能定位到函数级,且不需要事先知道原因。All reactions