docs(roadmap): known bug — HTTP/1.0 keep-alive honored but not advertised

Found benching with ab -k: a 1.0 request with Connection: Keep-Alive is
kept alive (second pipelined request answered on the same socket) but
the response never echoes the header. 1.0 clients only reuse on explicit
server opt-in, so they wait for EOF that never comes; ab -k deadlocks to
apr_pollset_poll timeout on the first response. Recorded with repro,
fix direction (echo header in serialise_response on live 1.0 conns, or
force-close 1.0), and the no-keep-alive baseline: GET /users, release,
loopback, logging silenced, c=50 -> ~18.9k req/s, p50 3ms / p99 5ms,
0 failed. Fix deliberately not started: scope (error responses, HEAD)
is a user call.
This commit is contained in:
Claude
2026-06-12 06:58:31 +00:00
parent d96ba88ec8
commit f5ccd640fb
+18
View File
@@ -227,6 +227,24 @@ PubSub underneath.
---
## Known bugs
- **HTTP/1.0 keep-alive: server honors but never advertises** (found
2026-06-12 via `ab -k`). A 1.0 request with `Connection: Keep-Alive`
IS kept alive (second pipelined request on the same socket gets
answered), but the response carries no `Connection: Keep-Alive`
header. Per 1.0 convention the client may only reuse when the server
explicitly opts in; absent the header, clients assume the server will
close and wait for EOF — which never comes. `ab -k` therefore
deadlocks until its poll timeout (`apr_pollset_poll: timeout 70007`)
on the FIRST response; no keep-alive bench numbers obtainable.
Fix direction: when the conn stays alive on a 1.0 exchange, echo
`Connection: Keep-Alive` in serialise_response — or don't keep 1.0
alive at all. Decide scope (error responses, HEAD) with user first.
Baseline for reference: GET /users (crud example, release, loopback,
stdout logging silenced), no keep-alive, c=50: ~18.9k req/s, 0
failed, p50 3ms / p99 5ms. HTTP/1.1 path responds normally.
## Later / icebox
- **HTTP/2** — spec §2.2 already designs the stream-actor demux (zero-copy