writeonce/docs/stories/runtime-v2/05-fd-passing.md
shoney.arickathil 3190b609af docs(rt2): track-wide brainstorm — all five iterations ready, graph remapped
- spec 2026-09-01-runtime-v2-design.md: the one principle (PULL — a
  child is fds, the net verbs drive them; runtime-v2 adds acquisition
  verbs, never transport), the full surface (ids 97+: spawn/spawn_pty/
  wait_dl/signal/resize, signal.on delivering the sig number, term.raw/
  restore with runtime-guaranteed restore, send_fd/recv_fd/connect_unix),
  actor-owned lifecycle, mechanics notes, refusals by name
- push transport rejected with reasons recorded (mailbox-cap collision,
  new delivery machinery); death-notice verb refused (a two-line fiber
  composes wait_dl)
- five stories flip readiness: ready; fork sections rewritten as settled
- graph section 6 remapped: pull broke the 1->2->3 chain — only 1->2
  remains; 3, 4, 5 and the VTE grid startable alone today
- board section + registry follow; linkcheck 0 broken

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

2.3 KiB

track iteration status readiness
runtime-v2 5 pending 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.