Skip to content

Commit 5c027c5

Browse files
committed
fix(ci): add output-stall watchdog to bst build retry loop
A full buildbarn pod-restart wave black-holes the bst gRPC stream with no error surfaced, so the NOT_FOUND hotfix never fires and the client hangs silently until the step timeout. Kill the named bst container after 65 min of total output silence and let the existing retry loop resume from the warm CAS. Assisted-by: Claude Fable 5 via GitHub Copilot
1 parent af645fc commit 5c027c5

2 files changed

Lines changed: 51 additions & 3 deletions

File tree

.github/workflows/build.yml

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -432,20 +432,46 @@ jobs:
432432
# dropped streams) fail the session instead of hanging; a re-run
433433
# resumes from the warm CAS in ~25 min. Only infra signatures are
434434
# retried — genuine build failures exit immediately.
435+
#
436+
# Stall watchdog: some RE flaps black-hole the client without any
437+
# gRPC error surfacing (observed 2026-07-10: full buildbarn pod
438+
# restart -> bst silent forever, NOT_FOUND hotfix never fired).
439+
# bst --no-interactive only prints on task events; the longest
440+
# observed single action is ~37 min (gcc-stage1), so 65 min of
441+
# total output silence means a dead client. The watchdog kills the
442+
# named bst container, which fails the pipe and trips the retry.
435443
set -o pipefail
436444
attempt=1
437445
max_attempts=3
446+
base_extra="${BST_PODMAN_EXTRA_ARGS:-}"
447+
stall_secs=3900
438448
while :; do
439449
rc=0
440-
just bst build ${{ matrix.element }} 2>&1 \
441-
| tee /tmp/bst-build-out.txt \
450+
: > /tmp/bst-build-out.txt
451+
cname="bst-build-${attempt}"
452+
(
453+
while :; do
454+
sleep 120
455+
mt=$(stat -c %Y /tmp/bst-build-out.txt 2>/dev/null || echo 0)
456+
if [ $(( $(date +%s) - mt )) -ge "$stall_secs" ]; then
457+
echo "STALL_WATCHDOG: no bst output for ${stall_secs}s — killing ${cname}" >> /tmp/bst-build-out.txt
458+
podman kill "${cname}" >/dev/null 2>&1 || true
459+
exit 0
460+
fi
461+
done
462+
) &
463+
wd=$!
464+
BST_PODMAN_EXTRA_ARGS="${base_extra} --name ${cname}" \
465+
just bst build ${{ matrix.element }} 2>&1 \
466+
| tee -a /tmp/bst-build-out.txt \
442467
| python3 files/scripts/bst-progress.py || rc=$?
468+
kill "$wd" 2>/dev/null || true
443469
[ "$rc" -eq 0 ] && break
444470
if [ "$attempt" -ge "$max_attempts" ]; then
445471
echo "::error::bst build failed after ${attempt} attempts (rc=${rc})"
446472
exit "$rc"
447473
fi
448-
if grep -qE "Operation with name .* not found|Failed contacting remote execution server|Stream removed|DEADLINE_EXCEEDED|Failed to contact remote execution endpoint" /tmp/bst-build-out.txt; then
474+
if grep -qE "STALL_WATCHDOG|Operation with name .* not found|Failed contacting remote execution server|Stream removed|DEADLINE_EXCEEDED|Failed to contact remote execution endpoint" /tmp/bst-build-out.txt; then
449475
attempt=$((attempt + 1))
450476
echo "::warning::RE infrastructure failure on attempt $((attempt - 1)) — retrying (warm cache resumes), attempt ${attempt}/${max_attempts}"
451477
else

docs/skills/ci.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2549,3 +2549,25 @@ GitHub-side fix (no cluster dependency), in build.yml:
25492549
Drop the hotfix when upstream BST treats lost operations as fatal (check the
25502550
fatal tuple in the image's `_sandboxremote.py`; the step then logs "already
25512551
handles NOT_FOUND upstream").
2552+
2553+
### Stall watchdog: some RE flaps black-hole bst with no error at all (2026-07-10)
2554+
2555+
The NOT_FOUND hotfix (above) only helps when the server *answers* with an
2556+
error. Observed on run 29093568343: a full buildbarn pod-restart wave
2557+
(frontend + scheduler + storage + workers all restarted at once) left the bst
2558+
client silent forever — no NOT_FOUND, no stream error, nothing. The gRPC
2559+
stream is simply black-holed and bst waits on it indefinitely.
2560+
2561+
Fix in build.yml build step: an output-stall watchdog subshell. Every attempt
2562+
runs the bst container with a known name (`--name bst-build-N` via
2563+
`BST_PODMAN_EXTRA_ARGS`); a background loop checks the mtime of
2564+
/tmp/bst-build-out.txt every 2 min and, after 65 min (3900 s) of total output
2565+
silence, writes a `STALL_WATCHDOG` marker into the file and `podman kill`s
2566+
the container. The killed pipe returns nonzero, the retry loop matches
2567+
STALL_WATCHDOG as an infra signature, and the next attempt resumes from the
2568+
warm CAS.
2569+
2570+
Threshold rationale: `bst --no-interactive` prints on task start/end events;
2571+
with multiple parallel builders the longest observed silent gap is well under
2572+
the ~37 min gcc-stage1 build. 65 min of *total* silence across all builders
2573+
means a dead client, not a slow compile. Do not lower this below ~45 min.

0 commit comments

Comments
 (0)