fix(cmux-tui-core): a key skips the creating-input lock while nothing is creating; the lock becomes a leaf (R-DAEMON-STATE S1 step 4)
Summary
R-DAEMON-STATE stage S1 step 4 (handoff/rewrites/R-DAEMON-STATE/DESIGN.md, section 3 and Appendix A.2 step 16). Base feat-cmux-next (S1.2, #34171, and S1.3, #34146, have landed). Behind the same per-mux switch CMUX_TUI_RDS_INPUT (default off).
Every key to a live terminal first asks whether creating input of its terminal must go first (wait_for_creating_input_flush, terminal-input-while-creating-v1). It took the daemon-wide creating-input lock even when no terminal was being created, and that lock's holders (begin_creating_input, knows_terminal_input_target, finish_creating_input) looked up the live terminal under it, which takes the session lock. So a key waited for any creation in progress and, behind it, for any holder of the session lock. The S1 census measured a full wait on the creating-input lock (300.3 ms, hosted run 41648095321).
With the switch on:
CreatingInputskeeps the number of creating terminals in an atomic, stored under its lock after every insert and removal (Release). A key reads it (Acquire) and returns at once when it is zero. No queue can be ahead of it then: a terminal's queue is added before the terminal goes live, and removed only after every queued byte was written to it.- The holders of the creating-input lock look up the live terminal in the published routes, not under the session lock. No holder waits for the session lock while it holds the creating-input lock, so a key that takes that lock (while another terminal is being created) never waits behind one. The routes carry the host-id catalog index for this:
terminal_catalog_by_hostbecomes a copy-on-write route table in theRouteSnapshot, and one lookup (route_table::live_terminal) serves the session state and the snapshot. - Why the creation checks keep their answers: a commit publishes its routes before it releases the session lock, and
finish_creating_inputruns after the commit (the old path could not call it under the session lock: it would deadlock), sobegin,knowsandfinishsee what they saw under the session lock.
With the switch off, every path takes the locks it took on the base. The by-host index is copy-on-write on both arms, as the other three route tables have been since step 1.
Testing
a_key_waits_for_no_creating_input_lock (cmux-tui/crates/cmux-tui-core/src/server/tests/rds_input_lane.rs): two keys through the real line path while another thread holds (1) the creating-input lock, (2) the session lock while a reader waits for it under the creating-input lock, with another terminal being created so the key cannot skip that lock. Each holder has an old-path control (switch off: the key must wait).
Focused command: ./scripts/verify-cmux-tui-hosted.sh --filter rds_input_lane.
- Red at eecb0d813a2 (
test/rds-s14-red-never-merge), hosted run https://github.com/manaflow-ai/cmux/actions/runs/41699822496:a_key_waits_for_no_creating_input_lockFAILED. Controls (lane off) 300.17 ms (creating-input lock) and 300.28 ms (session lock behind a creating-input reader); lane 300.24 ms and 300.36 ms. The other 5rds_input_lanetests passed. - Green at the head 8a502885dc1, hosted run https://github.com/manaflow-ai/cmux/actions/runs/41700308786: Linux
rds_input_lane6 of 6 passed. Its other jobs (lint (linux), macOS) fail on the old base's acpmux reds (login_env/watch.rsunused imports, fixed on feat by #33664 and #33690); this PR touches no acpmux file.
Compile: fleet job 862158b530775c4020d371bd at 8a502885dc1 passed (CmuxNext 282 s, app 94 s, cmux-tui 61 s).
- At the head 5aa3ec47572 (after #34146 and #34171 landed: their squashes merged with
-s ours, then feat 2e0b6acc359; this PR's own diff is unchanged, stable patch-id 5f12b0acf23e): hosted run https://github.com/manaflow-ai/cmux/actions/runs/41783051119,rds_input_lane6 of 6 passed; itslint (linux)red is base only (cmux-git/tests/sync_barrier.rs:108 redundant_clone, the panic ratchet rows of cmux-tui and cmux-vault-egress). Compile: fleet job 49f9b443e09b623932a07322 at the head passed.
Observed / Not run
- Observed: the hosted runs and the fleet compile above.
- Not run: the full cmux-tui suite on this head (with the stack, after the merge with feat); macOS execution of the focused test; the real-app A/B (after S1 lands).
Review follow-ups (head 8ee8220c728)
The review (comment 6613998735, SHIP at 8a502885dc1) left notes; taken in 3b2e29f1389:
- The
begin_creating_inputcomment now states the lane's linearization (it said the check takes the session state under the creating lock, which is the old path only). - The lane's live-terminal lookup takes the old read on a poisoned session state, as
Mux::surfacedoes since #34171's bb0265f43d5. - The stack's
unused_qualificationsred atmux/tests/signaled_mutex.rs:120is fixed in #34171 (10f16693a03), merged here.
Green at 8ee8220c728: hosted run https://github.com/manaflow-ai/cmux/actions/runs/41713709790, Linuxrds_input_lane6 of 6 passed.
Changelog
none
Proof
No capture: daemon-only change behind a default-off switch, no UI.