a73x

0e9b3215

fix: the coverage shim runs the word that forks bare, not every start

a73x   2026-08-30 10:11

Commit message
fix: the coverage shim runs the word that forks bare, not every start

`run` became `start`, and the shim's `start|endpoint) exec bare` — written
when `start` was only the launcher — swallowed every foreground daemon the
suite runs. `make coverage` went green measuring no daemon at all:
server.zig 0/819 lines, quic_server.zig 0/276.

The word that daemonises is `-d`, and it is now a word in one slot, so the
shim can read it exactly. Detached launchers stay bare; the plain
`mux d start` a scenario runs in the foreground is traced again — 373/819
and 225/276 over E2E_ONLY=01_boot alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wi2HnuF1EK8HgViU11YLV

test/coverage.sh
Old New
@@ -22,18 +22,22 @@
22 # the one signal a wrapper cannot forward, so a leg that kill -9s a 22 # the one signal a wrapper cannot forward, so a leg that kill -9s a
23 # daemon would leave the real one alive holding its socket. e2e.sh's 23 # daemon would leave the real one alive holding its socket. e2e.sh's
24 # hardkill answers that; see the comment there. 24 # hardkill answers that; see the comment there.
25 # - kcov waits for the LAST traced descendant, and `mux d start -d` daemonises: 25 # - kcov waits for the LAST traced descendant, and `mux d start -d`
26 # its launcher forks, the parent exits, and the daemon reparents to init. 26 # daemonises: the launcher forks, the parent exits, and the daemon
27 # Traced, that daemon outlives the scenario, so kcov never exits and the 27 # reparents to init. Traced, that daemon outlives the scenario, so kcov
28 # suite's `wait` on it never returns — a hang at the auto-start leg that 28 # never exits and the suite's `wait` on it never returns — a hang at the
29 # reads as a slow run, and one that ignores SIGTERM, so `timeout` will not 29 # auto-start leg that reads as a slow run, and one that ignores SIGTERM,
30 # free it either. The shims therefore run `start` BARE, exporting 30 # so `timeout` will not free it either. So the shim reads the WORD that
31 # MUX_KCOV_ACTIVE so the `mux d start -d` it re-execs stays bare too. The cost 31 # forks: `mux d start -d` runs bare, and the plain `mux d start` a
32 # is the auto-started daemons' lines; the alternative was a suite that 32 # scenario runs in the foreground is traced like anything else. That is
33 # could not finish. `endpoint` is the same shape one hop out: it spawns 33 # where server.zig's e2e lines come from, and widening the case back to
34 # the daemon it announces, and the ssh handoff client then kill()s its 34 # every `start` loses all of them for a gate that still goes green;
35 # ssh child and WAITS on it — which under the shim is kcov, holding on 35 # narrowing it to every `start` hangs the suite at the first `-d` leg.
36 # for that daemon. The handoff legs stalled there with attaches=0. 36 # The cost is the detached daemons' lines. `endpoint` is the same shape
37 # one hop out and stays bare whole: it spawns the daemon it announces,
38 # and the ssh handoff client then kill()s its ssh child and WAITS on it
39 # — which under the shim is kcov, holding on for that daemon. The
40 # handoff legs stalled there with attaches=0.
37 # 41 #
38 # Not --exit-first-process, which is kcov's own answer to daemons: it 42 # Not --exit-first-process, which is kcov's own answer to daemons: it
39 # reparents the tracer, and then the real process is no longer a CHILD of 43 # reparents the tracer, and then the real process is no longer a CHILD of
@@ -114,7 +118,10 @@ cat > "$SHIM/mux" <<SHIM_EOF
114 [ -n "\$MUX_KCOV_ACTIVE" ] && exec "$real" "\$@" 118 [ -n "\$MUX_KCOV_ACTIVE" ] && exec "$real" "\$@"
115 case "\${1:-}" in d|a|web) _m=\$1; _v=\${2:-} ;; *) _m=: ; _v=\${1:-} ;; esac 119 case "\${1:-}" in d|a|web) _m=\$1; _v=\${2:-} ;; *) _m=: ; _v=\${1:-} ;; esac
116 case " $TRACED " in *" \$_m "*) ;; *) exec "$real" "\$@" ;; esac 120 case " $TRACED " in *" \$_m "*) ;; *) exec "$real" "\$@" ;; esac
117 case "\$_v" in start|endpoint) exec "$real" "\$@" ;; esac 121 case "\$_m \$_v" in
122 "d endpoint") exec "$real" "\$@" ;;
123 "d start") case "\${3:-}" in -d|--detach) exec "$real" "\$@" ;; esac ;;
124 esac
118 MUX_KCOV_ACTIVE=1; export MUX_KCOV_ACTIVE 125 MUX_KCOV_ACTIVE=1; export MUX_KCOV_ACTIVE
119 exec kcov --collect-only "--include-path=$SRC" "$RAW/mux.\$\$" "$real" "\$@" 126 exec kcov --collect-only "--include-path=$SRC" "$RAW/mux.\$\$" "$real" "\$@"
120 SHIM_EOF 127 SHIM_EOF