a73x

224e0465

test: e2e — one peer holding half a frame does not stop muxd stats

a73x   2026-08-27 13:22

Commit message
test: e2e — one peer holding half a frame does not stop muxd stats

test/e2e.sh
Old New
@@ -94,6 +94,16 @@ done
94 echo " daemon can still report a command's real exit code" 94 echo " daemon can still report a command's real exit code"
95 exit 1; } 95 exit 1; }
96 96
97 # And a sixth: the half-frame leg has to put ONE byte on a unix socket and
98 # hold the connection open, which no shell builtin can do. python3 is the
99 # one tool every box this suite runs on already has; a skip here would let
100 # a daemon that blocks on a slow peer pass green.
101 command -v python3 > /dev/null 2>&1 || {
102 echo "e2e FAIL: this suite needs python3 (the half-frame scenario opens a raw"
103 echo " unix socket); install it, or lose the check that one stalled"
104 echo " peer cannot stop the daemon"
105 exit 1; }
106
97 # Where the scenarios live. This file is the runner: it hands the group 107 # Where the scenarios live. This file is the runner: it hands the group
98 # files a hermetic environment and an armed trap, sources them in order, 108 # files a hermetic environment and an armed trap, sources them in order,
99 # and owns the count pin at the bottom. It is deliberately the only place 109 # and owns the count pin at the bottom. It is deliberately the only place
@@ -167,8 +177,8 @@ done
167 # one of those and adds a convergence point would be pinning a fact every 177 # one of those and adds a convergence point would be pinning a fact every
168 # leg above already establishes. 178 # leg above already establishes.
169 179
170 [ "$OK_COUNT" = "82" ] || { 180 [ "$OK_COUNT" = "83" ] || {
171 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 82 —" 181 echo "e2e FAIL: $OK_COUNT scenario checkpoints ran, the pin says 83 —"
172 echo " a scenario was added (update the pin) or silently lost" 182 echo " a scenario was added (update the pin) or silently lost"
173 exit 1 183 exit 1
174 } 184 }
test/e2e_01_boot.sh
Old New
@@ -963,3 +963,45 @@ assert_converged "$OUT.g9" "$SOCK11" "goal commands"
963 softkill "$GPID" || true 963 softkill "$GPID" || true
964 GPID="" 964 GPID=""
965 ok "keygen + start --quic + mux quic:// with no --key anywhere" 965 ok "keygen + start --quic + mux quic:// with no --key anywhere"
966
967 # --- one stalled peer cannot stop the daemon --------------------------------
968 # A connection that writes the first byte of a frame and then holds still.
969 # Before this was fixed the daemon blocked in read() on that fd and every
970 # other connection — stats included — waited behind it (2026-08-27, found
971 # on a live wall). The witness is `muxd stats` answering within its timeout
972 # WHILE the half frame is still outstanding; the peer is only released after.
973 SOCKHF="${TMPDIR:-/tmp}/muxd-e2e-halfframe-$$.sock"
974 start_daemon "$SOCKHF" "$OUT.hf.d" "half-frame daemon never bound" --shell /bin/sh
975 DHFPID=$DPID
976 HFMARK="$OUT.hf.sent"; defer_rm "$HFMARK"
977 python3 - "$SOCKHF" "$HFMARK" <<'EOF' &
978 import socket, sys, time
979 s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
980 s.connect(sys.argv[1])
981 s.sendall(b'\x06') # stats_req's kind byte, and nothing after it
982 open(sys.argv[2], 'w').write('sent\n') # the byte is queued on the daemon's side
983 time.sleep(60)
984 EOF
985 HFPID=$!
986 defer_kill "$HFPID"
987 # The marker, not a sleep: the leg's whole precondition is that the half
988 # frame is ALREADY outstanding when stats connects. A timed settle that
989 # loses the race on a slow box asks a pre-fix daemon a question it can
990 # answer, and the leg goes green having tested nothing.
991 wait_for "$HFMARK" sent 5 || {
992 echo "e2e FAIL: half-frame: peer never connected"; tail -30 "$OUT.hf.d"; exit 1; }
993 set +e
994 timeout 5 "$MUXD" stats --sock "$SOCKHF" > "$OUT.hf.st" 2>&1
995 HFRC=$?
996 set -e
997 [ "$HFRC" -eq 0 ] || {
998 echo "e2e FAIL: half-frame: stats exited $HFRC with a one-byte peer outstanding"
999 echo " (124 = the daemon is blocked in read() behind that peer)"
1000 cat "$OUT.hf.st"; tail -30 "$OUT.hf.d"; exit 1; }
1001 grep -q 'sessions=' "$OUT.hf.st" || {
1002 echo "e2e FAIL: half-frame: stats answered but not with a stats line:"; cat "$OUT.hf.st"; exit 1; }
1003 softkill "$HFPID" || true
1004 HFPID=""
1005 softkill "$DHFPID" || true
1006 DHFPID=""
1007 ok "one peer holding half a frame does not stop muxd stats"