工程(挂死防护·probe_gate件): 十处套件换 run_suite 整树回收——启动记 WINPID,超时先 taskkill /T 杀全树再 kill -9 收 MSYS 侧(顺序颠倒会让 /T 走不到已死父进程,即原孤儿泄漏根源),标志文件判超时(taskkill 强杀后 MSYS wait 报 0)——默认五段实跑全绿残留0,超时/正常双路径机制验证通过;run_all.gd 阻塞面超时守护属代码面留待 worktree 批,条目保持待执行

This commit is contained in:
DKChan committed 2026-10-28 04:14:35 +08:00
1 parent 667a6060f8
commit 21cd0f2e05
2 files changed
+52 -22

No files matched your search

+51 -21
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env bash
# 探针闸正主——headless 安全段固化,禁再手拼同款 Godot 命令。
# 三闸:①每段 timeout 守卫(挂死=FAIL 不静默)②段前预清+段后清本 game 目录孤儿 Godot
# 三闸:①每段 timeout 守卫+超时整树回收(挂死=FAIL 不静默;taskkill /T 连引擎子进程一起杀,
# 不再只杀 wrapper 留孤儿)②段前预清+段后清本 game 目录孤儿 Godot
# (按命令行精确匹配本 game 路径,不误杀其他 worktree 会话的合法进程)③末尾残留清点=批末闸(必须 0)。
# 段:ui_input_probe=默认必跑;ui_struct_probe=默认必跑(
# 全 UI 屏结构断言:按钮互压/等宽/出屏/零尺寸/标题屏双列);ui_contrast_probe=默认必跑(
@@ -75,6 +76,35 @@ kill_orphans() {
local p; for p in $(orphans); do taskkill //F //PID "$p" >/dev/null 2>&1; done
}
# 每段跑批统一走本函数:后台启动记 MSYS PID→WINPID,守卫进程到点先 taskkill /T 整树回收
# (顺序要紧:先杀 wrapper 再清树会让 /T 走不到已死的父进程,引擎子进程照样泄漏——
# 2026-10-25 在册挂死根源),后 kill -9 收 MSYS 侧。正常退出不动进程树;段后 kill_orphans 照跑兜底。
run_suite() { # run_suite <timeout秒> <日志> <场景 res:// 路径>
local t="$1" log="$2" scene="$3"
local kf="$TMP/killed.$RANDOM"
rm -f "$kf"
"$G" --headless --path "$GAME_WIN" "$scene" >"$log" 2>&1 &
local pid=$!
local wpid=""
wpid="$(ps -W 2>/dev/null | awk -v p="$pid" '$1==p{print $4; exit}')"
( sleep "$t" 2>/dev/null
touch "$kf"
[ -n "$wpid" ] && taskkill //F //T //PID "$wpid" >/dev/null 2>&1
kill -9 "$pid" 2>/dev/null
true ) &
local guard=$!
wait "$pid"; local st=$?
kill "$guard" 2>/dev/null; wait "$guard" 2>/dev/null
# taskkill 强杀后 MSYS wait 可能报 0——超时判定以守卫落下的标志文件为准(与 124 同判)。
if [ "$st" -ge 128 ] || [ -f "$kf" ]; then
st=124
echo "[probe_gate] 套件超时(${t}s),已整树回收(PID=$pid/WINPID=${wpid:-未取到——靠孤儿清杀兜底})"
fi
rm -f "$kf"
kill_orphans
return "$st"
}
# 冷检出刷导入(.godot 不入 git,fresh worktree 首跑一次性付)
if [ ! -f "$GAME/.godot/uid_cache.bin" ]; then
echo "[probe_gate] 冷检出:editor --quit 刷导入(一次性,可到 1-2 分钟)"
@@ -86,39 +116,39 @@ pre="$(orphans | wc -l | tr -d ' ')"
if [ "$pre" -gt 0 ]; then echo "[probe_gate] 预清本闸残留 Godot×$pre"; kill_orphans; fi
echo "======== ui_input_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/ui_input_probe.tscn >"$TMP/uip.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/uip.log" res://probe/ui_input_probe.tscn
st=$?
grep -E "PASS|FAIL|问题" "$TMP/uip.log" | head -12
verdict "ui_input_probe" "$TMP/uip.log" "$st" || _rc=1
echo "======== ui_struct_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/ui_struct_probe.tscn >"$TMP/stp.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/stp.log" res://probe/ui_struct_probe.tscn
st=$?
grep -E "PASS|FAIL" "$TMP/stp.log" | head -12
verdict "ui_struct_probe" "$TMP/stp.log" "$st" || _rc=1
echo "======== layout_probe(分辨率几何·两档) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/layout_probe.tscn >"$TMP/lay.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/lay.log" res://probe/layout_probe.tscn
st=$?
grep -E "PASS|FAIL" "$TMP/lay.log" | head -12
verdict "layout_probe" "$TMP/lay.log" "$st" || _rc=1
echo "======== ui_contrast_probe ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/ui_contrast_probe.tscn >"$TMP/ctp.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/ctp.log" res://probe/ui_contrast_probe.tscn
st=$?
grep -E "PASS|FAIL" "$TMP/ctp.log" | head -12
verdict "ui_contrast_probe" "$TMP/ctp.log" "$st" || _rc=1
echo "======== screen_flow_probe(L3 屏壳切换·迭代 29 T4) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/screen_flow_probe.tscn >"$TMP/sfp.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/sfp.log" res://probe/screen_flow_probe.tscn
st=$?
grep -E "screen_flow_probe" "$TMP/sfp.log" | tail -3
verdict "screen_flow_probe" "$TMP/sfp.log" "$st" "screen_flow_probe" || _rc=1
if [ "$WITH_CLICK" -eq 1 ]; then
echo "======== ui_click_probe 行为走查 ========"
timeout 240 "$G" --headless --path "$GAME_WIN" res://probe/ui_click_probe.tscn >"$TMP/clk.log" 2>&1
st=$?; kill_orphans
run_suite 240 "$TMP/clk.log" res://probe/ui_click_probe.tscn
st=$?
grep -E "click_probe" "$TMP/clk.log" | tail -4
verdict "ui_click_probe" "$TMP/clk.log" "$st" "click_probe" || _rc=1
fi
@@ -127,26 +157,26 @@ fi
# ui_tune_probe 49.6s/t17_defer_probe 63.0s/fx_probe 21.9s,timeout 120=2-7×余量) ──
if [ "$WITH_FULL" -eq 1 ]; then
echo "======== ui_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/ui_probe.tscn >"$TMP/flp.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/flp.log" res://probe/ui_probe.tscn
st=$?
grep -E "\[ui_probe\]" "$TMP/flp.log" | tail -2
verdict "ui_probe" "$TMP/flp.log" "$st" || _rc=1
echo "======== ui_tune_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/ui_tune_probe.tscn >"$TMP/flt.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/flt.log" res://probe/ui_tune_probe.tscn
st=$?
grep -E "\[tune_probe\]" "$TMP/flt.log" | tail -2
verdict "ui_tune_probe" "$TMP/flt.log" "$st" || _rc=1
echo "======== t17_defer_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/t17_defer_probe.tscn >"$TMP/fld.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/fld.log" res://probe/t17_defer_probe.tscn
st=$?
grep -E "\[t17_defer\]" "$TMP/fld.log" | tail -2
verdict "t17_defer_probe" "$TMP/fld.log" "$st" || _rc=1
echo "======== fx_probe(--full 收编) ========"
timeout 120 "$G" --headless --path "$GAME_WIN" res://probe/fx_probe.tscn >"$TMP/flx.log" 2>&1
st=$?; kill_orphans
run_suite 120 "$TMP/flx.log" res://probe/fx_probe.tscn
st=$?
grep -E "\[fx_probe\]" "$TMP/flx.log" | tail -2
verdict "fx_probe" "$TMP/flx.log" "$st" || _rc=1
fi