feat(server): task-exit parking for idle connections — 19.8 → 3.25 KB/conn (c1M P1) - #422
Conversation
…/conn (c1M P1)
A monoio plain-TCP connection idle past --conn-park-secs (default 60 s,
0 = off) now has its handler task EXIT instead of sitting parked inside
the read future. The task returns MonoioHandlerResult::ParkIdle carrying
{Box<MigratedConnectionState>, RegistryGuard}; conn_accept spawns a tiny
boxed watcher future owning {TcpStream, state, guard, ConnectionContext}
that awaits stream.readable(false) (race-free on both io_uring and
kqueue/epoll — no vendor patch needed) or shard shutdown. On wake it
drops the registry guard synchronously and respawns the full handler
through the migration-restore path (can_migrate=false, can_park=true),
so a resumed connection can park again indefinitely.
Mechanism details:
- Stage-2 arm in handler_monoio/mod.rs splits: parkable requires
can_park && S::SUPPORTS_TASK_PARK && park_after_ms() > 0, empty
read/write buffers, !in_multi, empty command_queue, and no active
cross-shard txn. Subscribers, tracking conns, and `timeout N` conns
are structurally excluded (their select arms precede the park arm).
- idle_park sweep gains a stage2 flag per slot: stage-1 cancels at
IDLE_DOWNSHIFT_MS (1 s, probe-buffer downshift), stage-2 cancels at
conn_park_after_ms (task exit). TLS keeps SUPPORTS_TASK_PARK=false
(follow-up: readable() passthrough in the vendored wrapper).
- RegistryGuard hoisted to module scope and moved through ParkIdle so
deregister-before-fd-close holds on every path; CLIENT KILL's
shutdown(2) makes the parked fd read-ready, the watcher wakes, and
the resumed handler reads EOF. record_connection_closed fires exactly
once per connection (original task skips it on park; the watcher or
resumed task owns it).
- can_park is opt-in per call site: only sites that route ParkIdle pass
true (plain-TCP accept + resumed helper); TLS, fail-open, and
migrated-spawn sites pass false so a ParkIdle can never be silently
dropped (= closed). Follow-up noted to wire the migrated-spawn site.
- Known limitation (independent review, Low): on data-wake the
deregister→re-register window spans a task-scheduling boundary, so a
racing CLIENT LIST briefly misses the waking conn and CLIENT KILL ID
returns 0 (same observable as a reconnect race). Closing it needs
registration handoff into the handler; documented at the drop site.
- New flag plumbed via moon::runtime atomic (set_conn_park_secs);
tokio runtime warns and ignores it.
Measured (E10, moon-dev VM, 10 k idle conns, shards=2, same-binary
flag A/B, tmp/c10k/e10_park_rss.sh):
- PARK_OFF (W11 baseline): 19.8 KB/conn idle
- PARK_ON: 3.25 KB/conn idle; re-parks at 3.75 after a full wake sweep
- Wake sweep wire-correct: bad=0; 0.25 s vs 0.10 s for 10 k PINGs
(~15 µs/conn extra wake cost, off the hot path)
- Campaign total: 56.5 → 3.3 KB/idle-conn (−94 %); 1 M idle ≈ 3.3 GB
Gates:
- tests/parked_idle_parity.rs (new, 3 tests): multi-cycle park/wake
parity (probe, 100-deep pipeline, 4 KiB value), CLIENT LIST/KILL on
a parked conn, active-sibling isolation — green on kqueue (macOS)
AND io_uring (VM), plus tokio (degenerate parity)
- idle_park unit tests 10/10 incl. new stage2_uses_park_after_threshold
- VM monoio lib 4466 pass; tokio lib 3609 pass; W11 + TLS idle parity
suites still green
- fmt, clippy --all-targets (both matrices, 0 lints), unsafe/unwrap
audits pass
refs: .planning/rfcs/c1m-connection-plane.md (sequencing item 6, P1)
author: Tin Dang
📝 WalkthroughWalkthroughAdds configurable stage-2 task-exit parking for eligible monoio plain-TCP connections. Parked connections retain registry visibility, wake on readability or shutdown, and resume through a fresh handler task. Integration tests cover protocol continuity, client management, and sibling activity. ChangesConnection task parking
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant MonoioHandler
participant ParkedIdleWatcher
participant TcpStream
participant ClientRegistry
MonoioHandler->>TcpStream: Cancel idle stage-2 read
MonoioHandler->>ClientRegistry: Preserve registry entry
MonoioHandler->>ParkedIdleWatcher: Pass parked connection state
ParkedIdleWatcher->>TcpStream: Wait for readability or shutdown
TcpStream-->>ParkedIdleWatcher: Report readiness
ParkedIdleWatcher->>MonoioHandler: Resume connection handler
ParkedIdleWatcher->>ClientRegistry: Deregister on final close
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoTask-exit parking for idle monoio TCP connections via --conn-park-secs
AI Description
Diagram
High-Level Assessment
Files changed (11)
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@CHANGELOG.md`:
- Around line 9-25: Remove the duplicate ### Added heading around the task-exit
parking entry and fold that entry into the existing ### Added section within
[Unreleased], preserving the existing ### Fixed section and changelog ordering.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: e84fe1f9-c9cf-4e73-a53d-b09e6f96fcfd
📒 Files selected for processing (11)
CHANGELOG.mdsrc/config.rssrc/main.rssrc/runtime/mod.rssrc/server/conn/handler_monoio/idle_park.rssrc/server/conn/handler_monoio/mod.rssrc/shard/conn_accept.rstests/mq_integration.rstests/parked_idle_parity.rstests/txn_kv_wiring.rstests/workspace_integration.rs
| ### Added | ||
| - **Task-exit parking for idle connections (c1M P1, `--conn-park-secs`, | ||
| default 60 s).** A plain-TCP monoio connection that stays idle past the | ||
| W11 downshift now has its handler task exit entirely: only a tiny | ||
| readiness watcher (boxed future holding the stream, ~100 B of session | ||
| state, and the client-registry guard) remains, reclaiming the ~6 KB task | ||
| state machine plus the remaining per-task buffers. The watcher wakes on | ||
| read-readiness (`readable(false)`, race-free on io_uring and | ||
| epoll/kqueue) or server shutdown and rehydrates a fresh handler through | ||
| the migration-restore path — wire-invisible across repeated park/wake | ||
| cycles. Parked connections stay in CLIENT LIST, keep their maxclients | ||
| slot, and CLIENT KILL still works (its `shutdown(2)` wakes the watcher; | ||
| the resumed handler sees EOF). Exclusions: subscriber/tracking/timeout | ||
| connections (structurally never reach the park arm), MULTI/EXEC or | ||
| cross-store-txn sessions, partial frames, TLS (keeps W11+P4b buffer | ||
| downshift), and the tokio runtime. `--conn-park-secs 0` disables. | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Duplicate ### Added heading inside [Unreleased].
Line 53 already opens an ### Added section in the same release block (with ### Fixed in between). Fold this entry into the existing ### Added list so changelog tooling and readers see one section per change type.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@CHANGELOG.md` around lines 9 - 25, Remove the duplicate ### Added heading
around the task-exit parking entry and fold that entry into the existing ###
Added section within [Unreleased], preserving the existing ### Fixed section and
changelog ordering.
Code Review by Qodo
Context used✅ Compliance rules (platform):
55 rules 1. Unannotated unwrap() in tests
|
| if buf.starts_with(b"$") { | ||
| if let Some(pos) = buf.iter().position(|&b| b == b'\n') { | ||
| let len: usize = std::str::from_utf8(&buf[1..pos - 1]) | ||
| .unwrap() | ||
| .trim() | ||
| .parse() | ||
| .unwrap(); | ||
| if buf.len() >= pos + 1 + len + 2 { | ||
| break; |
There was a problem hiding this comment.
2. Unannotated unwrap() in tests 📘 Rule violation ✧ Quality
tests/parked_idle_parity.rs introduces multiple .unwrap() calls without the required // ... justification line and adjacent #[allow(clippy::unwrap_used)] attribute in scope. This violates the unwrap-audit policy and makes it harder to distinguish intentional invariant-based unwraps from accidental panics.
Agent Prompt
## Issue description
New `.unwrap()` calls were added without the required adjacent `#[allow(clippy::unwrap_used)]` and a one-line justification comment.
## Issue Context
The policy applies to unwraps in both application code and tests. This file has several unwraps (path conversion, RESP parsing, UTF-8 conversions) that need either removal (use `expect`/`match`) or explicit justification + allow.
## Fix Focus Areas
- tests/parked_idle_parity.rs[21-34]
- tests/parked_idle_parity.rs[77-84]
- tests/parked_idle_parity.rs[134-136]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| // Wake: the handler re-registers this client_id at entry, so drop | ||
| // the parked entry first. The deregistered window lasts until the | ||
| // executor first polls the resumed task (a task-scheduling boundary, | ||
| // not just a few instructions): a racing CLIENT LIST misses the | ||
| // conn and CLIENT KILL ID returns 0 — same observable as a | ||
| // reconnect race, and a kill_flag set in that window is superseded | ||
| // by the shutdown(2) the killer already issued, which is what woke | ||
| // us. Closing the gap needs registration handoff into the handler | ||
| // (pass the guard through instead of drop/re-register); not worth | ||
| // it for a transient-invisibility race on an actively-waking conn. | ||
| drop(registry_guard); | ||
| spawn_resumed_parked_conn(stream, state, conn_ctx, shutdown, client_id, kill_fd); |
There was a problem hiding this comment.
3. Client list age resets 🐞 Bug ≡ Correctness
On wake from task-exit parking, the watcher deregisters the connection and the resumed handler re-registers the same client_id, which recreates ClientLiveState timestamps so CLIENT LIST/INFO age/idle reset on every park/wake cycle despite the TCP connection never reconnecting.
Agent Prompt
### Issue description
Parked connections are deregistered on wake (`drop(registry_guard)`) and then re-registered by the resumed handler. Because `client_registry::register()` sets `connected_at = Instant::now()` and `connected_at_epoch_ms = current_time_ms()`, the same TCP connection appears “new” after each wake, resetting `CLIENT LIST`/`CLIENT INFO` `age` and distorting `idle`.
### Issue Context
This is user-visible Redis-compat output and can break monitoring/tooling that interprets `age`/`idle` as connection lifetime.
### Fix Focus Areas
- src/shard/conn_accept.rs[1016-1045]
- src/server/conn/handler_monoio/mod.rs[251-260]
- src/client_registry.rs[195-224]
- src/client_registry.rs[435-451]
### Suggested fix direction
Implement a “registry handoff” so the resumed handler does not create a fresh registry entry:
1. Pass the existing registry ownership into the resumed handler instead of `drop(registry_guard)` on wake. (This also eliminates the transient invisibility window.)
2. Update `handle_connection_sharded_monoio` to accept an optional pre-existing registry/live state (or an optional `RegistryGuard` + `Arc<ClientLiveState>`), and when provided, skip `client_registry::register()` and reuse the existing `ClientLiveState` so `connected_at`/`connected_at_epoch_ms` remain stable.
Alternative (if full handoff is too invasive): add a `client_registry::register_with_timestamps(...)` used only by parked-resume to preserve the original `connected_at`/`connected_at_epoch_ms` carried in `MigratedConnectionState`.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| let fut: std::pin::Pin<Box<dyn std::future::Future<Output = ()>>> = Box::pin(async move { | ||
| let woke = monoio::select! { | ||
| res = stream.readable(false) => { | ||
| // Err (fd error) also resumes: the handler's first read | ||
| // surfaces the real error and tears down cleanly. | ||
| let _ = res; | ||
| true | ||
| } | ||
| _ = shutdown.cancelled() => false, | ||
| }; | ||
| if !woke { | ||
| // Server shutdown: this watcher owns the close accounting. | ||
| drop(registry_guard); | ||
| drop(stream); | ||
| crate::admin::metrics_setup::record_connection_closed(); | ||
| return; |
There was a problem hiding this comment.
4. Guard/fd drop order not enforced 🐞 Bug ☼ Reliability
CLIENT KILL’s raw-fd shutdown safety relies on deregistration happening strictly before the socket fd closes; the new parked-idle watcher only enforces guard→stream drop order on the explicit shutdown branch, leaving other watcher teardown paths dependent on implicit drop behavior rather than an explicit invariant-preserving wrapper.
Agent Prompt
### Issue description
`client_registry::kill_clients` documents a lock-ordering + fd-liveness invariant: while a registry entry exists, its `kill_fd` must still refer to the live socket, which is ensured by dropping the registry guard (deregister) before closing the stream.
With task-exit parking, the stream + RegistryGuard live inside a spawned watcher future. The shutdown branch explicitly drops `registry_guard` before `stream`, but the code does not structurally enforce this ordering for *all* watcher teardown paths (e.g., early drops/unwinds), making the invariant easier to accidentally break.
### Issue Context
If the stream were ever dropped before the registry entry is removed, the registry can temporarily hold a `kill_fd` that has been closed and potentially reused by the OS, which is exactly what the documented invariant is avoiding.
### Fix Focus Areas
- src/shard/conn_accept.rs[1016-1047]
- src/client_registry.rs[308-316]
### Suggested fix direction
Make the guard→stream ordering unconditional by construction:
1. Introduce a small wrapper struct owned by the watcher, e.g.
```rust
struct ParkedOwned {
guard: RegistryGuard,
stream: monoio::net::TcpStream,
}
```
and keep it as a single value inside the watcher future.
2. Ensure the wrapper’s drop order (or a custom `Drop` impl) always deregisters before closing the stream.
3. In the wake path, destructure the wrapper and explicitly `drop(guard)` before handing `stream` to `spawn_resumed_parked_conn`.
This preserves the `kill_fd` liveness contract regardless of how the watcher future terminates.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
…conns −94%) (#423) Patch release rolling up the connection-plane campaign: PR #421 (rounds 1-4: W1-W8+T3, P3 future diet, P4a --uring-entries, W11 idle downshift, P4b TLS diet) and PR #422 (round 5: P1 task-exit parking), plus the SDK reconnect fix. Headline: idle-connection memory 56.5 → 3.25 KB/conn (−94%); 1 M idle connections ≈ 3.3 GB. Long-idle plain-TCP conns exit their handler task entirely (--conn-park-secs, default 60 s), leaving a tiny readiness watcher; wake is wire-invisible and re-parks indefinitely. TLS idle 87.5 → 47.4 KB/conn via vendored monoio-rustls/io-wrapper lazy+releasable buffers. Pipeline memory ratchet fixed (~217 KB permanent → 47 KB). Operability: loud maxclients -ERR + RLIMIT_NOFILE check, 16-way striped client registry, deadline-heap blocking sweep, SPSC drain rotation, affinity-funnel load gate. Validation: same-binary flag A/Bs on the Linux VM at 10 k conns for every memory wave; GCE t2a hardware proof (idle −46%, pinned p=1/p=16 perf-neutral); wire-parity suites across park/wake cycles green on kqueue AND io_uring; parked conns visible in CLIENT LIST and killable. This release touches no crash/persistence path; the crash-matrix + soak gate is dispatched on the RC to hold the ritual (soak-first-then-tag). Rolls CHANGELOG [Unreleased] into [0.8.3], bumps Cargo.toml/lock, adds the RELEASES.md row, updates the README milestone table. author: Tin Dang
…ration handoff, ECANCELED spin fix (#424) * fix(server): registration handoff across park/wake + migrated-conn parking (c1M P1 follow-ups) Two follow-ups from the round-5 task-exit-parking review: 1. Registration handoff (closes the review's Low finding, and a worse bug found while fixing it): waking a parked connection deregistered then re-registered the client across a task-scheduling boundary. Beyond the transient CLIENT LIST invisibility / KILL-returns-0 window, the fresh registration silently RESET the connection's CLIENT SETNAME and age (register() inserts name: None; only the SETNAME dispatch path ever sets it). The watcher now passes the held RegistryGuard through spawn_resumed_parked_conn into the handler (ParkArgs::kept_registration); the handler reuses the live entry via the new client_registry::live_handle() instead of re-registering. The entry — name, connected_at, kill state, TOTAL_CLIENTS/shard counters — persists unbroken across any number of park/wake cycles; there is no deregistered window at all. The can_park bool param becomes ParkArgs {can_park, kept_registration} with NO_PARK/PARK consts at the six monoio call sites. 2. Migrated-spawn site routes ParkIdle: a connection that migrated shards (Linux) and then idled past --conn-park-secs now parks like a primary-accept connection instead of holding its handler task forever. Mechanical mirror of the reviewed plain-TCP routing (same watcher, same close-accounting transfer). No dedicated migration integration harness exists (migration is affinity-driven, Linux-only); covered by compile gates + the shared watcher paths. Red/green: new tests/parked_idle_parity.rs test resumed_connection_keeps_registry_identity (SETNAME → 2× park/data-wake cycles → name+id survive, CLIENT LIST holds exactly victim+control) was RED before (name= empty, age=0 after wake), GREEN after. Gates: parked parity 4/4 on kqueue AND io_uring (VM); TLS parity green; VM monoio lib 4466 pass; VM tokio lib 3628 pass; fmt; clippy --all-targets both matrices 0 lints. refs: PR #422 review Low, .planning/rfcs/c1m-connection-plane.md author: Tin Dang * feat(server): TLS task-exit parking — idle TLS 47.0 → 26.0 KB/conn (c1M P1-TLS) Extends round-5 task-exit parking to TLS connections, closing the last c1M follow-up. No new unsafe; vendored additions are moon-patch style. Vendored (monoio-rustls + monoio-io-wrapper): - Stream::io_ref() — raw-transport reference so the parked watcher can await readable(false) on the underlying fd through the TLS wrapper. - Stream::task_park_safe() — park-safety veto: refuses while the TLS stack holds ANYTHING the raw fd's readability cannot signal (wrapper buffer bytes or pending EOF/error status via the new ReadBuffer/WriteBuffer::is_drained(), decrypted plaintext, a received close_notify, or pending session output). A partial record in the deframer is park-safe: completing it requires more socket bytes. - SafeRead/SafeWrite::is_drained() with moon-patch unit tests (7/7). moon: - IdleParkRead: TLS sets SUPPORTS_TASK_PARK=true; new per-park task_park_safe() hook (plain TCP: always true) appended LAST in the parkable predicate. - conn_accept: ParkWatchable trait (park_readable()) — TcpStream awaits its own readable(false), TLS awaits io_ref().readable(false); watcher + resume helpers genericized over the stream; the monoio-TLS accept site routes ParkIdle like the plain site. Spin bug found by E11 and fixed (affects plain TCP too): - The idle-park arms treated EVERY read error as the sweep cancel. With task parking, a dead connection whose error leaves the fd permanently readable (TLS client FIN without close_notify => read ERROR; plain RST) spun park→wake→park at 100% CPU forever — E11's first ON leg ended with 3000 CLOSE_WAIT conns and a pinned shard. The arms now match monoio's exact cancel error (raw os 125 on BOTH drivers — uring kernel -ECANCELED, legacy hardcodes 125): only the sweep cancel downshifts/parks, real errors tear down promptly (idle_park:: is_sweep_cancel). Small-N repro: fds released, 0 CLOSE_WAIT, 0% CPU. Measured (E11, moon-dev VM, 3000 idle TLS conns, shards=2, same-binary flag A/B, tmp/c10k/e11_tls_park_rss.sh): - TLSPARK_OFF (P4b downshift only): 47.0 KB/conn idle - TLSPARK_ON: 26.0 KB/conn idle (−45%); re-parks at 31.4 after a full wake sweep; sweeps bad=0 both legs; RSS + fds fully return on close - Remaining TLS floor ≈ rustls session (~15-20 KB, not shrinkable via public API) + registry entry + kernel socket Tests: - tls_idle_downshift_parity: +tls_parked_connection_serves_traffic_and_ stays_killable (3 park/wake cycles incl. 100-pipeline on ONE session; CLIENT LIST shows the parked conn WITH its name via registration handoff; CLIENT KILL closes it), +tls_fin_while_parked_tears_down_ promptly (the spin regression, TLS leg) - parked_idle_parity: +rst_while_parked_tears_down_promptly (spin regression, plain-TCP RST leg) - All parity suites green on kqueue AND io_uring (plain 5/5, TLS 3/3) Gates: VM monoio+tokio lib suites pass; E10 plain-park sanity re-run green; fmt; clippy --all-targets both matrices 0 lints; vendor wrapper moon-patch tests 7/7. refs: .planning/rfcs/c1m-connection-plane.md (P1-TLS follow-up) author: Tin Dang * fix(server): PR #424 review fixes — REPLCONF park exclusion, SAFETY comment, expect-free is_drained CodeRabbit review of PR #424, all three findings addressed: 1. (Major) PSYNC-after-park closed the replica connection: connections that have issued REPLCONF (replica mid-handshake, PSYNC next) are now permanently excluded from task-parking via a sticky ConnectionState::saw_replconf flag checked in the parkable predicate — the unsupported HijackForPsync warn+close arm on the resumed path is now unreachable for real replicas. (A manual PSYNC with no prior REPLCONF after 60s of idle still lands on the loud warn+close and the replica's reconnect loop recovers — documented.) 2. (Minor) SO_LINGER unsafe block in rst_while_parked test gained its required // SAFETY: comment. 3. (Minor) Vendored SafeRead/SafeWrite::is_drained() are expect-free: a transiently-absent buffer answers false ("don't park" is always the safe verdict) instead of panicking. Gates: parity suites green kqueue (plain 5/5, TLS 3/3); vendor wrapper 7/7; fmt; clippy --all-targets both matrices 0 lints. refs: PR #424 review threads author: Tin Dang
Summary
c1M campaign round 5 — Proposal 1 task-exit parking, the c1M lever from
.planning/rfcs/c1m-connection-plane.md. An idle monoio plain-TCP connection past--conn-park-secs(default 60 s,0= off) has its handler task exit instead of sitting parked inside the read future; only a tiny boxed watcher future survives, awaiting readiness or shutdown.No vendor patch needed: monoio's public
TcpStream::readable(relaxed=false)is a race-free standalone readiness await on both drivers (io_uring PollAdd, cancel-on-drop; legacy readiness + verifying poll), and task memory frees on future return.Mechanism
conn-park-secsgets its read cancelled with astage2marker; the handler returnsMonoioHandlerResult::ParkIdle { Box<MigratedConnectionState>, RegistryGuard }.spawn_parked_idle_watcherowns {stream, state, guard, ctx};select!sreadable(false)vs shutdown. On wake it drops the registry guard, then respawns the full handler via the migration-restore path (can_migrate=false, can_park=true→ re-parks indefinitely).can_park && SUPPORTS_TASK_PARK, empty read/write buffers,!in_multi, empty command queue, no cross-shard txn. Subscriber/tracking/timeout Nconns structurally never reach the park arm.can_parkis opt-in per call site so aParkIdlecan never be silently dropped (TLS/fail-open/migrated-spawn passfalse).shutdown(2)wakes the watcher and the resumed handler reads EOF.record_connection_closedfires exactly once per connection on every path.Measured (E10, moon-dev VM, 10 k idle conns, shards=2, same-binary flag A/B)
Campaign total: 56.5 → 3.3 KB/idle-conn (−94 %); 1 M idle ≈ 3.3 GB.
Gates
tests/parked_idle_parity.rs(3 tests): multi-cycle park/wake parity (probe, 100-deep pipeline, 4 KiB value), CLIENT LIST/KILL on a parked conn, active-sibling isolation — green on kqueue and io_uring (+ tokio degenerate).clippy --all-targetson both matrices (0 lints), unsafe/unwrap audits pass.Follow-ups (documented, unscheduled)
readable()passthrough in the vendored wrapper; TLS keepsSUPPORTS_TASK_PARK=false).ParkIdle(currentlycan_park=false).refs:
.planning/rfcs/c1m-connection-plane.md(Proposal 1, sequencing item 6),tmp/C10K-REVIEW.mdround-5 appendixSummary by CodeRabbit
CLIENT LISTand continue supportingCLIENT KILL.--conn-park-secsoption, defaulting to 60 seconds; set it to0to disable parking.