summaryrefslogtreecommitdiff
path: root/9ns/test/mntgen.sh
diff options
context:
space:
mode:
Diffstat (limited to '9ns/test/mntgen.sh')
-rwxr-xr-x9ns/test/mntgen.sh49
1 files changed, 38 insertions, 11 deletions
diff --git a/9ns/test/mntgen.sh b/9ns/test/mntgen.sh
index aade76c..7dada53 100755
--- a/9ns/test/mntgen.sh
+++ b/9ns/test/mntgen.sh
@@ -254,14 +254,18 @@ echo "# --debug and --no-direct-io reach the mntgen dispatcher"
DEBUG_ERR=$(timeout 60 "$NS" --mntgen --debug -- sh -c "ls $M/alpha >/dev/null" 2>&1 >/dev/null)
expect_contains "--debug traces the dispatcher" "lookup 'alpha'" "$DEBUG_ERR"
-echo "# a dial parked on a mute server unwedges when the program exits"
-# A server that accepts the connection but never answers Tversion parks the
-# dispatcher in the dial (pinned: no dial timeout, no concurrent dial). The
-# dial must watch stop_fd through the whole handshake: when the program's
-# main flow exits while a background walk is parked there, 9ns must follow it
-# out instead of wedging forever (pre-fix it survived SIGTERM).
+echo "# a mute server costs only the walks into its own name"
+# A server that accepts the connection but never answers Tversion. The dial
+# runs on that name's worker, inside the walk that asked, so: every other
+# name (and the root) keeps answering; a signal releases the parked walker
+# at once (the dial is abandoned, EINTR); a fresh walk parks again and is
+# just as interruptible; and when the program exits with a walk still
+# parked, 9ns follows it out. Background jobs of a non-interactive sh ignore
+# SIGINT, so the parked walker is sent SIGTERM; the foreground `timeout -s
+# INT` case covers Ctrl-C. Pre-fix the dial ran on the dispatcher thread and
+# parked the whole mount, unkillably, until the program exited.
if command -v python3 > /dev/null; then
- python3 - "$REG/mute" <<'PYEOF' &
+ python3 - "$REG/mute" <<'MUTEEOF' &
import socket, sys, os
path = sys.argv[1]
try:
@@ -273,22 +277,45 @@ s.bind(path)
s.listen(8)
while True:
conn, _ = s.accept() # accept, then never say a word
-PYEOF
+MUTEEOF
MUTEPID=$!
PIDS+=($MUTEPID)
sleep 0.3
+ MUTE_OUT=$(timeout 60 "$NS" --mntgen -- sh -c '
+ stat '"$M"'/mute >/dev/null 2>&1 & W=$!
+ sleep 0.3
+ echo "alpha=$(timeout 5 cat '"$M"'/alpha/build/zig_version)"
+ echo "root=$(timeout 5 ls '"$M"' | grep -c .)"
+ echo "readdir_alpha=$(timeout 5 ls '"$M"'/alpha | grep -c .)"
+ s=$(date +%s%N); kill -TERM $W; wait $W; echo "term_rc=$? term_ms=$(( ($(date +%s%N) - s) / 1000000 ))"
+ s=$(date +%s%N); timeout -s INT 2 stat '"$M"'/mute >/dev/null 2>&1; echo "int_rc=$? int_ms=$(( ($(date +%s%N) - s) / 1000000 ))"
+ echo "alpha_again=$(timeout 5 cat '"$M"'/alpha/build/zig_version)"
+ ' 2>"$TMP/mute.err")
+ expect_eq "another name is served while a walk into mute is parked" "alpha=$(zig version)" "$(printf '%s\n' "$MUTE_OUT" | grep '^alpha=')"
+ ROOT_N=$(printf '%s\n' "$MUTE_OUT" | sed -n 's/^root=//p')
+ [ -n "$ROOT_N" ] && [ "$ROOT_N" -ge 2 ] && pass "the root lists while a walk into mute is parked ($ROOT_N entries)" || fail "the root listing did not answer" "$MUTE_OUT"
+ READDIR_N=$(printf '%s\n' "$MUTE_OUT" | sed -n 's/^readdir_alpha=//p')
+ [ -n "$READDIR_N" ] && [ "$READDIR_N" -ge 1 ] && pass "a readdir on another name is served meanwhile" || fail "readdir on alpha did not answer" "$MUTE_OUT"
+ expect_eq "SIGTERM releases the parked walker (died of the signal)" "term_rc=143" "$(printf '%s\n' "$MUTE_OUT" | sed -n 's/^\(term_rc=[0-9]*\) .*/\1/p')"
+ TERM_MS=$(printf '%s\n' "$MUTE_OUT" | sed -n 's/.*term_ms=//p')
+ [ -n "$TERM_MS" ] && [ "$TERM_MS" -lt 1500 ] && pass "released promptly (${TERM_MS}ms)" || fail "release of the parked walker was slow or missing" "term_ms=$TERM_MS"
+ expect_eq "a fresh walk into mute is interruptible (Ctrl-C after 2s)" "int_rc=124" "$(printf '%s\n' "$MUTE_OUT" | sed -n 's/^\(int_rc=[0-9]*\) .*/\1/p')"
+ INT_MS=$(printf '%s\n' "$MUTE_OUT" | sed -n 's/.*int_ms=//p')
+ [ -n "$INT_MS" ] && [ "$INT_MS" -ge 1900 ] && [ "$INT_MS" -lt 4000 ] && pass "the interrupted walk came back on the signal (${INT_MS}ms)" || fail "interrupted walk timing off" "int_ms=$INT_MS"
+ expect_eq "alpha still served after all that" "alpha_again=$(zig version)" "$(printf '%s\n' "$MUTE_OUT" | grep '^alpha_again=')"
+
HANG_START=$(date +%s)
timeout 20 "$NS" --mntgen -- bash -c "(stat $M/mute >/dev/null 2>&1) & sleep 1" >/dev/null 2>&1
HANG_RC=$?
HANG_SECONDS=$(( $(date +%s) - HANG_START ))
if [ "$HANG_RC" -eq 124 ] || [ "$HANG_SECONDS" -ge 15 ]; then
- fail "9ns unwedges after the program exits a parked dial" "rc=$HANG_RC after ${HANG_SECONDS}s (wedged)"
+ fail "9ns exits with a walk still parked in a dial" "rc=$HANG_RC after ${HANG_SECONDS}s (wedged)"
else
- pass "9ns unwedges after the program exits a parked dial (rc=$HANG_RC after ${HANG_SECONDS}s)"
+ pass "9ns exits with a walk still parked in a dial (rc=$HANG_RC after ${HANG_SECONDS}s)"
fi
rm -f "$REG/mute"
else
- echo "SKIP: mute-server dial-hang check needs python3"
+ echo "SKIP: mute-server checks need python3"
fi
echo