a73x

0c377dce

tools: harden valgrind-quic.sh failure paths

a73x   2026-08-14 09:36

Commit message
tools: harden valgrind-quic.sh failure paths

Four fixes from review, all on paths that only matter when something
has already gone wrong:

- stop is now `|| kill $VGPID || true` — a crashed-mid-run daemon no
  longer lets errexit delete vg.log unprinted, and a stop-ignoring live
  daemon gets killed instead of hanging the wait.
- INT/TERM traps now `exit`, not just clean up — Ctrl-C mid-bind-loop
  used to kill valgrind and rm $TMP while the loop kept polling the
  now-deleted socket path for up to a minute.
- the bind loop checks `kill -0 "$VGPID"` each tick and cats the log on
  timeout, so a daemon that dies at startup under valgrind fails fast
  instead of waiting out the full 60s.
- --error-exitcode=99 is no longer swallowed by `wait || true`; the
  valgrind exit code is captured and printed ahead of the summary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

tools/valgrind-quic.sh
Old New
@@ -18,8 +18,10 @@ command -v valgrind >/dev/null || { echo "valgrind is not installed"; exit 1; }
18 [ -x "$MUXD" ] && [ -x "$MUXA" ] || { echo "binaries missing — run zig build"; exit 1; } 18 [ -x "$MUXD" ] && [ -x "$MUXA" ] || { echo "binaries missing — run zig build"; exit 1; }
19 TMP="${TMPDIR:-/tmp}/mux-valgrind-$$" 19 TMP="${TMPDIR:-/tmp}/mux-valgrind-$$"
20 mkdir -p "$TMP" 20 mkdir -p "$TMP"
21 trap 'kill "$VGPID" 2>/dev/null; rm -rf "$TMP"' EXIT INT TERM
22 VGPID="" 21 VGPID=""
22 trap '[ -n "$VGPID" ] && kill "$VGPID" 2>/dev/null || true; rm -rf "$TMP"' EXIT
23 trap 'exit 130' INT
24 trap 'exit 143' TERM
23 # Hermetic key: keygen into a private XDG home, --key it explicitly. 25 # Hermetic key: keygen into a private XDG home, --key it explicitly.
24 XDG_CONFIG_HOME="$TMP/cfg"; export XDG_CONFIG_HOME 26 XDG_CONFIG_HOME="$TMP/cfg"; export XDG_CONFIG_HOME
25 "$MUXD" keygen > /dev/null 27 "$MUXD" keygen > /dev/null
@@ -30,17 +32,22 @@ valgrind --leak-check=full --error-exitcode=99 --log-file="$TMP/vg.log" \
30 "$MUXD" run --sock "$SOCK" --shell /bin/sh \ 32 "$MUXD" run --sock "$SOCK" --shell /bin/sh \
31 --quic "127.0.0.1:$PORT" --key "$KEY" & 33 --quic "127.0.0.1:$PORT" --key "$KEY" &
32 VGPID=$! 34 VGPID=$!
33 # valgrind start is SLOW; give the bind a full minute. 35 # valgrind start is SLOW; give the bind a full minute. Bail early if the
36 # daemon dies under valgrind instead of waiting out the whole timeout.
34 i=0 37 i=0
35 while [ ! -S "$SOCK" ] && [ "$i" -lt 600 ]; do sleep 0.1; i=$((i + 1)); done 38 while [ ! -S "$SOCK" ] && [ "$i" -lt 600 ]; do
36 [ -S "$SOCK" ] || { echo "daemon never bound under valgrind"; exit 1; } 39 kill -0 "$VGPID" 2>/dev/null || break
40 sleep 0.1; i=$((i + 1))
41 done
42 [ -S "$SOCK" ] || { echo "daemon never bound under valgrind:"; cat "$TMP/vg.log" 2>/dev/null; exit 1; }
37 # One real command over QUIC — handshake, frames, teardown — with a 43 # One real command over QUIC — handshake, frames, teardown — with a
38 # timeout sized for valgrind's clock, then a clean stop so every exit 44 # timeout sized for valgrind's clock, then a clean stop so every exit
39 # path (and the allocator teardown) runs. 45 # path (and the allocator teardown) runs.
40 "$MUXA" run --quic "127.0.0.1:$PORT" --key "$KEY" --timeout 60000 "echo vg-probe" \ 46 "$MUXA" run --quic "127.0.0.1:$PORT" --key "$KEY" --timeout 60000 "echo vg-probe" \
41 || echo "muxa run failed under valgrind (timing?) — the leak summary below still stands" 47 || echo "muxa run failed under valgrind (timing?) — the leak summary below still stands"
42 "$MUXD" stop --sock "$SOCK" 48 "$MUXD" stop --sock "$SOCK" || kill "$VGPID" 2>/dev/null || true
43 wait "$VGPID" || true 49 wait "$VGPID" && VGRC=0 || VGRC=$?
44 VGPID="" 50 VGPID=""
51 echo "valgrind exit: $VGRC (99 = valgrind-detected errors)"
45 echo "---- valgrind summary ----" 52 echo "---- valgrind summary ----"
46 grep -E "definitely lost|indirectly lost|ERROR SUMMARY" "$TMP/vg.log" || cat "$TMP/vg.log" 53 grep -E "definitely lost|indirectly lost|ERROR SUMMARY" "$TMP/vg.log" || cat "$TMP/vg.log"