writeonce/docs/stories/runtime-v2/05-fd-passing.md
shoney.arickathil 6e997759e5 docs(rt2): close out runtime-v2 1-5
- five stories status: done; 00-story records the one-run landing
- spec History: three implementation amendments (Signal record not
  scalar, caller-owned stdio fds, handler-latch instead of signalfd)
- board NEXT PLAN entry with measured findings (zero transport code
  added; the tty-across-the-socket handover proven; the double-raw
  refusal restoring the terminal — the "bug" that was the design
  working); section rows flipped; graph nodes green
- CODE-LOGIC.md: the runtime-v2 section
- full belt quoted on the board: suites 0 fail both flavors (test_proc
  193/0, test_term 60/0), woc 557/0, subprocess 12/0, site 23/0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit bc1b4f070693eb755ad6a9fd0c853fb3e2bda347)
2026-09-15 01:15:30 +02:00

2.3 KiB

track iteration status readiness
runtime-v2 5 done ready

runtime-v2 5 — fd passing: SCM_RIGHTS over the unix socket

Part of Story — runtime-v2: the runtime beyond sockets. No incoming edges — startable alone, any time. Promoted from the alacritty study's Wayland stage by the tmux study: the multiplexer needs it FIRST — a wmux client hands its tty fd to the server over the unix socket, the server writes escape sequences directly to the client's terminal, and detach is just the client process dying. That handover IS the tmux architecture (.dev/reference/tmux compat/imsg-buffer.c, proc.c).

The problem. net.listen_unix exists (iteration 35) but a byte stream is all it carries; an fd cannot cross it. sendmsg with SCM_RIGHTS ancillary data is the only mechanism, and it is runtime work by nature.

Info — the forks, settled (brainstorm 2026-09-01; spec:

2026-09-01-runtime-v2-design.md)

  1. Two verbs, fd travels alone: net.send_fd(conn, fd) -> Bool / net.recv_fd(conn) -> ?Int — sendmsg + SCM_RIGHTS, fixed ancillary buffer; framing stays the caller's ordinary bytes (the tmux imsg shape, composed in .wo).
  2. A received fd is a plain Int every existing fd verb accepts — net reads/writes, termios adoption included.
  3. This iteration CARRIES net.connect_unix(path) -> Int — iteration 38 verified pending at brainstorm time, not assumed.
  4. One fd per message, refusal by name past it; non-unix sockets refuse by name; multi-fd arrays wait for a consumer.

Acceptance sketch

  • A test parent and child (via 1) pass an open pipe fd across a unix socket; bytes written on one side arrive on the other through the RECEIVED fd.
  • A tty fd crosses and 4's verbs work on it — the wmux handover in miniature.
  • Refusals: passing on a non-unix socket, receiving where none was sent — both by name, neither a hang.
  • fd hygiene: the churn leg, passing edition — counts flat.

Consumers

wmux 1 (detach/attach), the alacritty study's stage D (Wayland needs SCM_RIGHTS for shm buffers), and — the board's porch 2 aside — nothing else yet, which is exactly why the surface stays two verbs.