a73x

866031d9

test: the coverage run survives two verbs the tracer wrapped wrong

a73x   2026-08-26 17:01

Commit message
test: the coverage run survives two verbs the tracer wrapped wrong

`make coverage` had never finished the suite. Two stops, both the same
disease as the documented `start` case — a pid the suite holds that is
kcov, not the process:

- `muxd endpoint` spawns the daemon it announces, and the ssh handoff
  client then kill()s and WAITS on its ssh child. Under the shim that
  child is kcov, holding on for the traced daemon; the client blocked
  before ever attaching (attaches=0 on the daemon). Run `endpoint` bare,
  as `start` is.
- A plain `kill $PID` to a wrapper is dropped — ptrace intercepts
  signals for the tracee, the tracer has no handler — so the hub leg's
  wait_pid_gone timed out. `softkill` is hardkill's TERM twin: it
  signals the tracee and lets the wrapper exit with its database.

Reaches scenario 74 of 82; the stop there is a muxa race the tracer
made deterministic, fixed separately.

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

test/coverage.sh
Old New
@@ -30,7 +30,10 @@
30 # free it either. The shims therefore run `start` BARE, exporting 30 # free it either. The shims therefore run `start` BARE, exporting
31 # MUX_KCOV_ACTIVE so the `muxd run` it re-execs stays bare too. The cost 31 # MUX_KCOV_ACTIVE so the `muxd run` it re-execs stays bare too. The cost
32 # is the auto-started daemons' lines; the alternative was a suite that 32 # is the auto-started daemons' lines; the alternative was a suite that
33 # could not finish. 33 # could not finish. `endpoint` is the same shape one hop out: it spawns
34 # the daemon it announces, and the ssh handoff client then kill()s its
35 # ssh child and WAITS on it — which under the shim is kcov, holding on
36 # for that daemon. The handoff legs stalled there with attaches=0.
34 # 37 #
35 # Not --exit-first-process, which is kcov's own answer to daemons: it 38 # Not --exit-first-process, which is kcov's own answer to daemons: it
36 # reparents the tracer, and then the real process is no longer a CHILD of 39 # reparents the tracer, and then the real process is no longer a CHILD of
@@ -113,7 +116,7 @@ for w in $WRAP; do
113 #!/bin/sh 116 #!/bin/sh
114 [ -n "\$MUX_KCOV_ACTIVE" ] && exec "$real" "\$@" 117 [ -n "\$MUX_KCOV_ACTIVE" ] && exec "$real" "\$@"
115 MUX_KCOV_ACTIVE=1; export MUX_KCOV_ACTIVE 118 MUX_KCOV_ACTIVE=1; export MUX_KCOV_ACTIVE
116 [ "\${1:-}" = start ] && exec "$real" "\$@" 119 case "\${1:-}" in start|endpoint) exec "$real" "\$@" ;; esac
117 exec kcov --collect-only "--include-path=$SRC" "$RAW/$w.\$\$" "$real" "\$@" 120 exec kcov --collect-only "--include-path=$SRC" "$RAW/$w.\$\$" "$real" "\$@"
118 SHIM_EOF 121 SHIM_EOF
119 chmod +x "$SHIM/$w" 122 chmod +x "$SHIM/$w"
test/e2e.sh
Old New
@@ -684,6 +684,22 @@ hardkill() {
684 kill -9 "$1" 2>/dev/null || true 684 kill -9 "$1" 2>/dev/null || true
685 } 685 }
686 686
687 # hardkill's TERM twin. A signal sent to a kcov wrapper is dropped: ptrace
688 # intercepts signals bound for the TRACEE, and the tracer has no handler of
689 # its own — measured on the hub leg, where `kill $W3PID` left both alive and
690 # wait_pid_gone timed out. TERM the tracee; the wrapper exits with it and
691 # writes its database. Off the tracer this is a plain kill, same exit status.
692 softkill() {
693 if [ "$(ps -o comm= -p "$1" 2>/dev/null)" = kcov ]; then
694 _rc=1
695 for _c in $(ps -o pid= --ppid "$1" 2>/dev/null); do
696 kill "$_c" 2>/dev/null && _rc=0
697 done
698 return $_rc
699 fi
700 kill "$1" 2>/dev/null
701 }
702
687 # Poll until nothing answers on a socket path (2s). Keyed off the daemon's 703 # Poll until nothing answers on a socket path (2s). Keyed off the daemon's
688 # own liveness rather than a fixed sleep, same reasoning as wait_for. 704 # own liveness rather than a fixed sleep, same reasoning as wait_for.
689 wait_gone() { 705 wait_gone() {
@@ -2427,7 +2443,7 @@ timeout 30 "$MUX" "quic://127.0.0.1:$QPORT" --key "$QKEY.wrong" \
2427 RC=$? 2443 RC=$?
2428 set -e 2444 set -e
2429 QT1=$(date +%s%N) 2445 QT1=$(date +%s%N)
2430 kill "$QWPID" 2>/dev/null || true 2446 softkill "$QWPID" || true
2431 rm -f "$QFIFO" 2447 rm -f "$QFIFO"
2432 QMS=$(( (QT1 - QT0) / 1000000 )) 2448 QMS=$(( (QT1 - QT0) / 1000000 ))
2433 [ "$RC" -eq 0 ] || { 2449 [ "$RC" -eq 0 ] || {
@@ -2567,7 +2583,7 @@ SNAPS_NQ=$("$MUXD" stats --sock "$SOCK4" | sed -n 's/.*snapshots=\([0-9]*\).*/\1
2567 } 2583 }
2568 assert_converged "$OUT.qk" "$SOCK4" "quic epoch resync" 2584 assert_converged "$OUT.qk" "$SOCK4" "quic epoch resync"
2569 2585
2570 kill "$D4PID" 2>/dev/null || true 2586 softkill "$D4PID" || true
2571 D4PID="" 2587 D4PID=""
2572 2588
2573 # --- M10: the daemon's own key resolution, over a real handshake. 2589 # --- M10: the daemon's own key resolution, over a real handshake.
@@ -2588,7 +2604,7 @@ grep -q "envkey-ok" "$OUT.env1" || {
2588 echo "e2e FAIL: MUX_KEY_FILE daemon served no session" 2604 echo "e2e FAIL: MUX_KEY_FILE daemon served no session"
2589 cat "$OUT.env1" "$OUT.env1.err" 2>/dev/null; exit 1; } 2605 cat "$OUT.env1" "$OUT.env1.err" 2>/dev/null; exit 1; }
2590 assert_converged "$OUT.env1" "$SOCK9" "env key" 2606 assert_converged "$OUT.env1" "$SOCK9" "env key"
2591 kill "$D9PID" 2>/dev/null || true 2607 softkill "$D9PID" || true
2592 D9PID="" 2608 D9PID=""
2593 2609
2594 # 2. --key AND MUX_KEY_FILE, naming different keys. The env names one the 2610 # 2. --key AND MUX_KEY_FILE, naming different keys. The env names one the
@@ -2609,7 +2625,7 @@ grep -q "flagwins-ok" "$OUT.env2" || {
2609 echo "e2e FAIL: --key-beats-env daemon served no session" 2625 echo "e2e FAIL: --key-beats-env daemon served no session"
2610 cat "$OUT.env2" "$OUT.env2.err" 2>/dev/null; exit 1; } 2626 cat "$OUT.env2" "$OUT.env2.err" 2>/dev/null; exit 1; }
2611 assert_converged "$OUT.env2" "$SOCK10" "flag beats env" 2627 assert_converged "$OUT.env2" "$SOCK10" "flag beats env"
2612 kill "$D10PID" 2>/dev/null || true 2628 softkill "$D10PID" || true
2613 D10PID="" 2629 D10PID=""
2614 ok "daemon honours MUX_KEY_FILE, and --key beats it" 2630 ok "daemon honours MUX_KEY_FILE, and --key beats it"
2615 2631
@@ -2674,12 +2690,12 @@ TPID=$(sed -n 's/.* pid=\([0-9]*\).*/\1/p' "$OUT.start")
2674 SHRUNK=$(stat -c %s "$MUXLOG") 2690 SHRUNK=$(stat -c %s "$MUXLOG")
2675 [ "$SHRUNK" -lt "$PADDED" ] || { 2691 [ "$SHRUNK" -lt "$PADDED" ] || {
2676 echo "e2e FAIL: log not truncated on spawn ($PADDED -> $SHRUNK)"; exit 1; } 2692 echo "e2e FAIL: log not truncated on spawn ($PADDED -> $SHRUNK)"; exit 1; }
2677 kill "$TPID" 2>/dev/null || true 2693 softkill "$TPID" || true
2678 TPID="" 2694 TPID=""
2679 2695
2680 # Race: two concurrent starts, both exit 0, still one session (the marker 2696 # Race: two concurrent starts, both exit 0, still one session (the marker
2681 # survives — a second daemon on the path would have started a fresh shell). 2697 # survives — a second daemon on the path would have started a fresh shell).
2682 kill "$SPID" && wait_gone "$SOCK8" 2698 softkill "$SPID" && wait_gone "$SOCK8"
2683 SPID="" 2699 SPID=""
2684 "$MUXD" start --sock "$SOCK8" 2> "$OUT.ra" & RA=$! 2700 "$MUXD" start --sock "$SOCK8" 2> "$OUT.ra" & RA=$!
2685 "$MUXD" start --sock "$SOCK8" 2> "$OUT.rb" & RB=$! 2701 "$MUXD" start --sock "$SOCK8" 2> "$OUT.rb" & RB=$!
@@ -2719,7 +2735,7 @@ grep -q "already running" "$OUT.rb" || {
2719 # `muxd run` between the two touches no session, so the grid has not moved. 2735 # `muxd run` between the two touches no session, so the grid has not moved.
2720 assert_converged "$OUT.race" "$SOCK8" "start race" 2736 assert_converged "$OUT.race" "$SOCK8" "start race"
2721 2737
2722 kill "$SPID" 2>/dev/null || true 2738 softkill "$SPID" || true
2723 SPID="" 2739 SPID=""
2724 ok "muxd start — spawn, no-op rerun, log truncation, race" 2740 ok "muxd start — spawn, no-op rerun, log truncation, race"
2725 2741
@@ -2771,7 +2787,7 @@ pipe_detach
2771 echo "e2e FAIL: no-key-flag QUIC attach did not reach the session" 2787 echo "e2e FAIL: no-key-flag QUIC attach did not reach the session"
2772 cat "$OUT.g9" "$OUT.g9.err" 2>/dev/null; exit 1; } 2788 cat "$OUT.g9" "$OUT.g9.err" 2>/dev/null; exit 1; }
2773 assert_converged "$OUT.g9" "$SOCK11" "goal commands" 2789 assert_converged "$OUT.g9" "$SOCK11" "goal commands"
2774 kill "$GPID" 2>/dev/null || true 2790 softkill "$GPID" || true
2775 GPID="" 2791 GPID=""
2776 ok "keygen + start --quic + mux quic:// with no --key anywhere" 2792 ok "keygen + start --quic + mux quic:// with no --key anywhere"
2777 2793
@@ -2921,7 +2937,7 @@ want_stat "$OUT.pb.err" contradicted 0 "burst"
2921 } 2937 }
2922 assert_converged "$OUT.pb" "$SOCK5" "burst" 2938 assert_converged "$OUT.pb" "$SOCK5" "burst"
2923 2939
2924 kill "$D5PID" 2>/dev/null || true 2940 softkill "$D5PID" || true
2925 D5PID="" 2941 D5PID=""
2926 2942
2927 # 3. A password prompt. The session is canonical with echo OFF from the 2943 # 3. A password prompt. The session is canonical with echo OFF from the
@@ -2980,7 +2996,7 @@ fi
2980 } 2996 }
2981 assert_converged "$OUT.pw" "$SOCK6" "password" 2997 assert_converged "$OUT.pw" "$SOCK6" "password"
2982 2998
2983 kill "$D6PID" 2>/dev/null || true 2999 softkill "$D6PID" || true
2984 D6PID="" 3000 D6PID=""
2985 3001
2986 # 4. Raw mode: display is earned, then lost to a keystroke the application 3002 # 4. Raw mode: display is earned, then lost to a keystroke the application
@@ -3049,7 +3065,7 @@ assert_converged "$OUT.rw" "$SOCK7" "raw mode"
3049 # 3065 #
3050 # A fresh daemon: the rawmode above has taken its 0x00 and echoes 3066 # A fresh daemon: the rawmode above has taken its 0x00 and echoes
3051 # nothing now, and the leg needs the insert-mode half back. 3067 # nothing now, and the leg needs the insert-mode half back.
3052 kill "$D7PID" 2>/dev/null || true 3068 softkill "$D7PID" || true
3053 wait "$D7PID" 2>/dev/null || true 3069 wait "$D7PID" 2>/dev/null || true
3054 rm -f "$SOCK7" 3070 rm -f "$SOCK7"
3055 "$MUXD" run --sock "$SOCK7" --shell "$RAWMODE" > "$OUT.rwl.d" 2>&1 & 3071 "$MUXD" run --sock "$SOCK7" --shell "$RAWMODE" > "$OUT.rwl.d" 2>&1 &
@@ -3076,7 +3092,7 @@ grep -q "$(printf '\033\[4m')" "$OUT.rwl" && {
3076 } 3092 }
3077 assert_converged "$OUT.rwl" "$SOCK7" "raw mode local" 3093 assert_converged "$OUT.rwl" "$SOCK7" "raw mode local"
3078 3094
3079 kill "$D7PID" 2>/dev/null || true 3095 softkill "$D7PID" || true
3080 D7PID="" 3096 D7PID=""
3081 3097
3082 # 5. A transport torn down with predictions outstanding. The overlay must 3098 # 5. A transport torn down with predictions outstanding. The overlay must
@@ -3144,7 +3160,7 @@ want_stat "$OUT.pr.err" expired 0 "reconnect"
3144 } 3160 }
3145 assert_converged "$OUT.pr" "$SOCK5" "reconnect flush" 3161 assert_converged "$OUT.pr" "$SOCK5" "reconnect flush"
3146 3162
3147 kill "$D5PID" 2>/dev/null || true 3163 softkill "$D5PID" || true
3148 D5PID="" 3164 D5PID=""
3149 3165
3150 # ---- M12: ptyclient fixture controls ---------------------------------- 3166 # ---- M12: ptyclient fixture controls ----------------------------------
@@ -3377,7 +3393,7 @@ rm_swept "$OUT.tp2a" "$OUT.tp2a.err" "$OUT.tp2a.log" \
3377 # Closed here like every other per-scenario daemon, not left to the trap: 3393 # Closed here like every other per-scenario daemon, not left to the trap:
3378 # tp1 runs below and would otherwise share the box with a daemon nobody is 3394 # tp1 runs below and would otherwise share the box with a daemon nobody is
3379 # watching, holding a session whose shell is still alive. 3395 # watching, holding a session whose shell is still alive.
3380 kill "$D12PID" 2>/dev/null || true 3396 softkill "$D12PID" || true
3381 D12PID="" 3397 D12PID=""
3382 ok "a pty client resizes: snapshot prefix applied, winch follows the tty" 3398 ok "a pty client resizes: snapshot prefix applied, winch follows the tty"
3383 3399
@@ -3553,7 +3569,7 @@ fi
3553 rm_swept "$OUT.tp1.doc" "$OUT.tp1.doc.render" "$OUT.tp1.doc.dump" \ 3569 rm_swept "$OUT.tp1.doc" "$OUT.tp1.doc.render" "$OUT.tp1.doc.dump" \
3554 "$OUT.tp1.doc.render.n" "$OUT.tp1.doc.dump.n" "$OUT.tp1.doc.diff" \ 3570 "$OUT.tp1.doc.render.n" "$OUT.tp1.doc.dump.n" "$OUT.tp1.doc.diff" \
3555 "$OUT.tp1.doc.rvt" "$OUT.tp1.doc.dvt" 3571 "$OUT.tp1.doc.rvt" "$OUT.tp1.doc.dvt"
3556 kill "$D13PID" 2>/dev/null || true 3572 softkill "$D13PID" || true
3557 D13PID="" 3573 D13PID=""
3558 rm_swept "$OUT.tp1" "$OUT.tp1.err" "$OUT.tp1.log" "$OUT.tp1.d" "$TP1SH" 3574 rm_swept "$OUT.tp1" "$OUT.tp1.err" "$OUT.tp1.log" "$OUT.tp1.d" "$TP1SH"
3559 ok "reconnect while scrolled: view restored, prediction resumed" 3575 ok "reconnect while scrolled: view restored, prediction resumed"
@@ -4696,7 +4712,7 @@ EOF
4696 fi 4712 fi
4697 done 4713 done
4698 4714
4699 kill "$W3PID" 2>/dev/null || true 4715 softkill "$W3PID" || true
4700 wait_pid_gone "$W3PID" "M18 wall: hub killed by tracked pid" 4716 wait_pid_gone "$W3PID" "M18 wall: hub killed by tracked pid"
4701 W3PID="" 4717 W3PID=""
4702 assert_stopped "$SOCK22" "$D19PID" "M18 wall" "$OUT.m18wstop" 4718 assert_stopped "$SOCK22" "$D19PID" "M18 wall" "$OUT.m18wstop"
@@ -4928,7 +4944,7 @@ CLIENTS_AFTER=$("$MUXD" stats --sock "$SOCK19" | sed -n 's/.*clients=\([0-9]*\).
4928 pipe_detach "web hub: typing client" 4944 pipe_detach "web hub: typing client"
4929 assert_converged "$OUT.webb" "$SOCK19" "web hub: the typing client" 4945 assert_converged "$OUT.webb" "$SOCK19" "web hub: the typing client"
4930 4946
4931 kill "$W1PID" 2>/dev/null || true 4947 softkill "$W1PID" || true
4932 wait_pid_gone "$W1PID" "web hub: killed by tracked pid" 4948 wait_pid_gone "$W1PID" "web hub: killed by tracked pid"
4933 W1PID="" 4949 W1PID=""
4934 assert_stopped "$SOCK19" "$D15PID" "web hub" "$OUT.webstop2" 4950 assert_stopped "$SOCK19" "$D15PID" "web hub" "$OUT.webstop2"
@@ -4994,7 +5010,7 @@ WCLIPID=""
4994 5010
4995 assert_ws_converged "$OUT.webws2" "$SOCK20" "web tear: after the epoch crossing" 5011 assert_ws_converged "$OUT.webws2" "$SOCK20" "web tear: after the epoch crossing"
4996 5012
4997 kill "$W2PID" 2>/dev/null || true 5013 softkill "$W2PID" || true
4998 wait_pid_gone "$W2PID" "web tear: hub killed by tracked pid" 5014 wait_pid_gone "$W2PID" "web tear: hub killed by tracked pid"
4999 W2PID="" 5015 W2PID=""
5000 # Its own capture, not a second write to $OUT.webstop3: that file still 5016 # Its own capture, not a second write to $OUT.webstop3: that file still
@@ -5149,7 +5165,7 @@ grep -qxF -- "--sock $SOCK25#b" "$DWSTATE/mux/wall" || {
5149 5165
5150 # Restart with NO argv: the file is the wall. The id is fresh — a restarted 5166 # Restart with NO argv: the file is the wall. The id is fresh — a restarted
5151 # hub numbers from 0 in wall order — and the SPELLING is what persisted. 5167 # hub numbers from 0 in wall order — and the SPELLING is what persisted.
5152 kill "$W4PID" 2>/dev/null || true 5168 softkill "$W4PID" || true
5153 wait_pid_gone "$W4PID" "dyn wall: first hub killed by tracked pid" 5169 wait_pid_gone "$W4PID" "dyn wall: first hub killed by tracked pid"
5154 XDG_STATE_HOME="$DWSTATE" "$MUXWEB" --port "$WPORT4" > "$OUT.dwh2" 2>&1 & 5170 XDG_STATE_HOME="$DWSTATE" "$MUXWEB" --port "$WPORT4" > "$OUT.dwh2" 2>&1 &
5155 W4PID=$! 5171 W4PID=$!
@@ -5169,7 +5185,7 @@ curl -s "$DWORIG/tiles" | grep -q "^\[{\"id\":0,\"label\":\"--sock $SOCK25#b\""
5169 # forgetting stays explicit — the page's `x`, the wall's `x`, `mux wall rm`. 5185 # forgetting stays explicit — the page's `x`, the wall's `x`, `mux wall rm`.
5170 # The tile is spelled as ONE quoted argument — the wall file's own 5186 # The tile is spelled as ONE quoted argument — the wall file's own
5171 # spelling, handed back to the binary that wrote it. 5187 # spelling, handed back to the binary that wrote it.
5172 kill "$W4PID" 2>/dev/null || true 5188 softkill "$W4PID" || true
5173 wait_pid_gone "$W4PID" "dyn wall: restored hub killed by tracked pid" 5189 wait_pid_gone "$W4PID" "dyn wall: restored hub killed by tracked pid"
5174 XDG_STATE_HOME="$DWSTATE" "$MUXWEB" "--sock $SOCK25" --port "$WPORT4" > "$OUT.dwh3" 2>&1 & 5190 XDG_STATE_HOME="$DWSTATE" "$MUXWEB" "--sock $SOCK25" --port "$WPORT4" > "$OUT.dwh3" 2>&1 &
5175 W4PID=$! 5191 W4PID=$!
@@ -5189,7 +5205,7 @@ grep -qxF -- "--sock $SOCK25#b" "$DWSTATE/mux/wall" || {
5189 echo "e2e FAIL: dyn wall: the wall file is not the two lines argv added to:" 5205 echo "e2e FAIL: dyn wall: the wall file is not the two lines argv added to:"
5190 cat "$DWSTATE/mux/wall"; exit 1; } 5206 cat "$DWSTATE/mux/wall"; exit 1; }
5191 5207
5192 kill "$W4PID" 2>/dev/null || true 5208 softkill "$W4PID" || true
5193 wait_pid_gone "$W4PID" "dyn wall: overriding hub killed by tracked pid" 5209 wait_pid_gone "$W4PID" "dyn wall: overriding hub killed by tracked pid"
5194 W4PID="" 5210 W4PID=""
5195 assert_stopped "$SOCK25" "$D22PID" "dyn wall" "$OUT.dwstop" 5211 assert_stopped "$SOCK25" "$D22PID" "dyn wall" "$OUT.dwstop"
@@ -7100,7 +7116,7 @@ D42PID=""
7100 # The agent has no more work; ended here rather than in the trap so a green 7116 # The agent has no more work; ended here rather than in the trap so a green
7101 # run does not leave a key-holding process alive for the length of the 7117 # run does not leave a key-holding process alive for the length of the
7102 # teardown. The trap still names it, for every run that does not reach here. 7118 # teardown. The trap still names it, for every run that does not reach here.
7103 kill "$AGENT48PID" 2>/dev/null || true 7119 softkill "$AGENT48PID" || true
7104 AGENT48PID="" 7120 AGENT48PID=""
7105 # The measurement is printed on a PASSING run too, not just quoted in the 7121 # The measurement is printed on a PASSING run too, not just quoted in the
7106 # failure above: the band this leg's ceiling was chosen against lives in 7122 # failure above: the band this leg's ceiling was chosen against lives in
@@ -7254,9 +7270,9 @@ D43PID=""
7254 # Ended here rather than in the trap, for the reason the leg above gives: 7270 # Ended here rather than in the trap, for the reason the leg above gives:
7255 # a green run should not leave two key-holding processes alive for the 7271 # a green run should not leave two key-holding processes alive for the
7256 # length of the teardown. The trap still names them. 7272 # length of the teardown. The trap still names them.
7257 kill "$AGENT49APID" 2>/dev/null || true 7273 softkill "$AGENT49APID" || true
7258 AGENT49APID="" 7274 AGENT49APID=""
7259 kill "$AGENT49BPID" 2>/dev/null || true 7275 softkill "$AGENT49BPID" || true
7260 AGENT49BPID="" 7276 AGENT49BPID=""
7261 ok "agent forwarding: the agent that answers is whoever typed last" 7277 ok "agent forwarding: the agent that answers is whoever typed last"
7262 7278
@@ -7603,7 +7619,7 @@ set -e
7603 # The agent is resumed before it is killed: a stopped process ignores 7619 # The agent is resumed before it is killed: a stopped process ignores
7604 # SIGTERM until it runs again, and the trap's plain kill would leave it. 7620 # SIGTERM until it runs again, and the trap's plain kill would leave it.
7605 kill -CONT "$AGENT48PID" 2>/dev/null || true 7621 kill -CONT "$AGENT48PID" 2>/dev/null || true
7606 kill "$AGENT48PID" 2>/dev/null || true 7622 softkill "$AGENT48PID" || true
7607 AGENT48PID="" 7623 AGENT48PID=""
7608 # The needles are split in the typed lines (`mu""te1=`) so an expect can 7624 # The needles are split in the typed lines (`mu""te1=`) so an expect can
7609 # only be satisfied by the command's OUTPUT, never by the pty's echo of the 7625 # only be satisfied by the command's OUTPUT, never by the pty's echo of the
@@ -7786,7 +7802,7 @@ ok "a focused tile's scrollback page owns only its sub-rect, and the neighbour's
7786 # is only reached by a run that passed, and a leak deserves reporting on the 7802 # is only reached by a run that passed, and a leak deserves reporting on the
7787 # runs that did not (see leak_sweep). Everything below it is a pin, and the 7803 # runs that did not (see leak_sweep). Everything below it is a pin, and the
7788 # trap fires after all of them either way. 7804 # trap fires after all of them either way.
7789 kill "$DPID" 2>/dev/null || true 7805 softkill "$DPID" || true
7790 wait "$DPID" 2>/dev/null || true 7806 wait "$DPID" 2>/dev/null || true
7791 DPID="" 7807 DPID=""
7792 7808
@@ -9002,7 +9018,7 @@ timeout 20 "$MUXA" status --sock "$SOCK67" --session wghost > "$OUT.wgexit" 2>&1
9002 cat "$OUT.wgexit"; exit 1; } 9018 cat "$OUT.wgexit"; exit 1; }
9003 wait_sessions "$SOCK67" 1 "web-restore: the ended session was not resurrected" 9019 wait_sessions "$SOCK67" 1 "web-restore: the ended session was not resurrected"
9004 9020
9005 kill "$W5PID" 2>/dev/null || true 9021 softkill "$W5PID" || true
9006 wait_pid_gone "$W5PID" "web-restore: hub killed by tracked pid" 9022 wait_pid_gone "$W5PID" "web-restore: hub killed by tracked pid"
9007 W5PID="" 9023 W5PID=""
9008 assert_stopped "$SOCK67" "$D67PID" "web-restore" "$OUT.wgstop" 9024 assert_stopped "$SOCK67" "$D67PID" "web-restore" "$OUT.wgstop"
@@ -9093,7 +9109,7 @@ timeout 20 "$MUXA" status --sock "$SOCK68" --session spinghost > "$OUT.spghost"
9093 echo "e2e FAIL: refusal-spin: a remote wall line created a session:" 9109 echo "e2e FAIL: refusal-spin: a remote wall line created a session:"
9094 cat "$OUT.spghost"; exit 1; } 9110 cat "$OUT.spghost"; exit 1; }
9095 9111
9096 kill "$W6PID" 2>/dev/null || true 9112 softkill "$W6PID" || true
9097 wait_pid_gone "$W6PID" "refusal-spin: hub killed by tracked pid" 9113 wait_pid_gone "$W6PID" "refusal-spin: hub killed by tracked pid"
9098 W6PID="" 9114 W6PID=""
9099 assert_stopped "$SOCK68" "$D68PID" "refusal-spin" "$OUT.spstop" 9115 assert_stopped "$SOCK68" "$D68PID" "refusal-spin" "$OUT.spstop"
@@ -9535,7 +9551,7 @@ pipe_detach "agent-upgrade client"
9535 9551
9536 assert_stopped "$SOCK71" "$D71PID" "agent-upgrade" "$OUT.uagstop" 9552 assert_stopped "$SOCK71" "$D71PID" "agent-upgrade" "$OUT.uagstop"
9537 D71PID="" 9553 D71PID=""
9538 kill "$UPAGPID" 2>/dev/null || true 9554 softkill "$UPAGPID" || true
9539 wait_pid_gone "$UPAGPID" "agent-upgrade: ssh-agent killed by tracked pid" 9555 wait_pid_gone "$UPAGPID" "agent-upgrade: ssh-agent killed by tracked pid"
9540 UPAGPID="" 9556 UPAGPID=""
9541 ok "the session's agent socket crosses the exec: ssh-add -l answers again" 9557 ok "the session's agent socket crosses the exec: ssh-add -l answers again"