Skip to content

hardening: idle/keep-alive timeouts and per-reactor connection caps #97

Description

@MDA2AV

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions