writeonce/docs/stories/runtime-v2/03-signals-as-events.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.4 KiB

track iteration status readiness
runtime-v2 3 pending ready

runtime-v2 3 — signals as events: SIGWINCH into a mailbox

Part of Story — runtime-v2: the runtime beyond sockets. The seam iteration 42 deliberately deferred "to its real consumer" — this is that consumer arriving. A terminal application's resize IS a signal (SIGWINCH), and nothing today can turn a signal into anything a program observes except the SIGTERM/SIGINT stop latch.

The problem. Signals are process-global, delivered on an arbitrary thread, and allowed to do almost nothing — the exact opposite of a shard-owned mailbox message. The runtime already crossed this bridge once: the stop flag is a signal made safe by latching. This iteration generalizes that shape without handing user code a signal handler.

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

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

  1. signal.on(sig, addr) — a standing subscription delivering the SIGNAL NUMBER as a scalar message. No moved-message ownership rules: scalars copy, so a repeating SIGWINCH needs no per-delivery payload.
  2. signalfd on shard 0's plane — one more registered fd with a sentinel user_data (the wake-eventfd precedent); reads drain signalfd_siginfo records and fan out ordinary sends.
  3. Offerable set: SIGWINCH, SIGCHLD, SIGHUP, SIGUSR1, SIGUSR2. SIGTERM/SIGINT registration is refused by name — the stop latch stays the engine's, iteration 40 is load-bearing.
  4. Coalescing disclosed, not sequenced — what SIGWINCH consumers expect anyway.

Also settled: this iteration is STANDALONE — the old edge from PTY was only the resize pairing; signalfd needs nothing from iteration 2.

Acceptance sketch

  • Resize the controlling terminal of a test child: the registered actor receives the message; the grid-owning code calls 2's resize onward — the wmux wiring, proven in miniature.
  • SIGCHLD registration does not disturb 42's pidfd machinery (they coexist; the pidfd stays the reap path).
  • SIGTERM still stops the engine with the full drain — the iteration 40 battery unchanged.

Consumers

wmux 1 (SIGWINCH fan-out to panes). Everything else can wait — this iteration exists exactly once a real consumer does, per 42's deferral.