From 3c0d315a9c2661d6ed1df8c281f861d990be08e7 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Wed, 29 Jul 2026 22:32:16 +0800 Subject: [PATCH] ci: sample runner state during the nextest step (#5440) The Test and Lint lane intermittently stalls until the inner 75m timeout kills the cargo process group (issue #5394). The evidence collected since #5402 shows the stall can begin in the build phase before any test runs (run 30449339653: last output at minute 4 of the nextest step, then 71 silent minutes until SIGTERM), but the post-mortem pgrep always reports nothing because GNU timeout has already terminated the whole process group by the time it runs. Add a background sampler to the nextest step that appends system and process snapshots (loadavg, PSI, memory, disk, top-RSS processes, cargo/rustc/linker/build-script processes, D-state processes) to the existing test-and-lint artifact every 60 seconds, and record kernel OOM/kill events in the post-mortem diagnostics. The last samples before a timeout identify the wedged process or the resource pressure that caused the stall. This only instruments the failure mode where the runner survives; jobs whose runner disappears entirely still upload no artifacts and need runner-pool-side logs. Refs #5394 --- .github/workflows/ci.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e24bd278..27a806a2e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -175,6 +175,33 @@ jobs: - name: Run nextest tests run: | mkdir -p artifacts/test-and-lint + # Evidence sampler for issue #5394: the post-mortem pgrep below runs + # only after `timeout` has already TERM'd the whole cargo process + # group, so it cannot name a wedged process. Sample system and + # process state every 60s instead; the last samples before the + # timeout show what was stuck (rustc, linker, build script, memory + # pressure, ...). The log rides along in the existing artifact. + ( + while true; do + { + echo "=== $(date --utc --iso-8601=seconds)" + echo "--- load"; cat /proc/loadavg + echo "--- psi"; grep -H . /proc/pressure/* 2>/dev/null || true + echo "--- mem"; free -m + echo "--- disk"; df -h / /home/runner 2>/dev/null || df -h / + echo "--- top-rss" + ps -eo pid,ppid,stat,etime,rss,pcpu,args --sort=-rss | head -15 + echo "--- build/test processes" + ps -eo pid,ppid,stat,etime,rss,pcpu,args | grep -E '[c]argo|[r]ustc|[n]extest|[c]ollect2|rust-ll[d]|[b]uild-script|deps[/]' || true + echo "--- d-state (uninterruptible IO)" + ps -eo pid,stat,etime,args | awk 'NR > 1 && $2 ~ /D/' || true + echo + } >> artifacts/test-and-lint/sampler.log 2>&1 || true + sleep 60 + done + ) & + sampler_pid=$! + trap 'kill "${sampler_pid}" 2>/dev/null || true' EXIT set +e NEXTEST_HIDE_PROGRESS_BAR=1 timeout --verbose --signal=TERM --kill-after=30s 75m \ cargo nextest run --profile ci --all --exclude e2e_test \ @@ -188,6 +215,9 @@ jobs: echo echo "Remaining test-related processes:" pgrep -af 'cargo|nextest|target/.*/deps/' || true + echo + echo "Kernel OOM / kill events:" + dmesg -T 2>/dev/null | grep -iE 'oom|out of memory|killed process' | tail -20 || true } > artifacts/test-and-lint/nextest-diagnostics.txt exit "${status}"