Severity: medium (high if deployed directly internet-facing rather than behind an LB/proxy).
Problem — two related gaps
1. No idle-connection reaping. A client that connects and goes silent holds, forever: an fd, a pooled Connection with its native write slab, a recv-queue, and in incremental mode a registered 64 KB buffer ring plus a gid (a hard-capped resource — see the gid-exhaustion issue). Slowloris-style header dribble is likewise unbounded: there is no clock anywhere in the connection lifecycle.
2. No concurrent-connection cap in shared mode. Track grows the connection table without bound (Reactor.cs#L112-L124) and multishot accept is always re-armed; the only backstop is RLIMIT_NOFILE. Incremental mode has MaxConnections, but enforcement is currently a crash (separate issue) rather than shedding.
Suggested fix
- Last-activity stamp on
Connection, updated in the recv-completion and send-completion paths (both already touch the connection object; a coarse Environment.TickCount64 store is enough).
- A ticker sweep over the connection table closing connections idle beyond
ServerConfig.IdleTimeout (0 = disabled). The AddTicker infrastructure already exists and 250 ms granularity is plenty for second-scale timeouts. Teardown path = the existing cancel + MarkClosed + DecRef sequence the recv-error path uses.
- Honor a
MaxConnections cap in shared mode too: at cap, either close-on-accept (shed) or pause the accept re-arm until below cap (real backpressure).
- Later, at the HTTP layer: header-read timeout / max header size — out of scope for the core transport but worth tracking.
Severity: medium (high if deployed directly internet-facing rather than behind an LB/proxy).
Problem — two related gaps
1. No idle-connection reaping. A client that connects and goes silent holds, forever: an fd, a pooled
Connectionwith its native write slab, a recv-queue, and in incremental mode a registered 64 KB buffer ring plus a gid (a hard-capped resource — see the gid-exhaustion issue). Slowloris-style header dribble is likewise unbounded: there is no clock anywhere in the connection lifecycle.2. No concurrent-connection cap in shared mode.
Trackgrows the connection table without bound (Reactor.cs#L112-L124) and multishot accept is always re-armed; the only backstop isRLIMIT_NOFILE. Incremental mode hasMaxConnections, but enforcement is currently a crash (separate issue) rather than shedding.Suggested fix
Connection, updated in the recv-completion and send-completion paths (both already touch the connection object; a coarseEnvironment.TickCount64store is enough).ServerConfig.IdleTimeout(0 = disabled). TheAddTickerinfrastructure already exists and 250 ms granularity is plenty for second-scale timeouts. Teardown path = the existing cancel +MarkClosed+DecRefsequence the recv-error path uses.MaxConnectionscap in shared mode too: at cap, either close-on-accept (shed) or pause the accept re-arm until below cap (real backpressure).