#63 serve: unbounded thread-per-connection + 500ms ack sleep = trivial availability DoS
hu13 serve is thread-per-connection with no cap, and every inbox response sleeps 500 ms.
Verified:
before: 1 thread
$ python3 open 300 idle sockets sending "GET / HTTP/1.1\r\nHost: x\r\n" (no terminator)
during: 301 threads VmRSS 11.8 MB
Those sockets cost nothing per connection and can be kept alive indefinitely (a byte every < read timeout). ~10-30k cheap sockets exhaust the thread/pid limit or memory, and the server stops accepting.
Amplifiers:
- inbox handler always
sleep(ACK_DELAY_MS)(500 ms) before answering, on every path including 400/403/429 — a rejected POST holds a thread for half a second settle()will additionally read up to 256 KiB from a lyingContent-Lengthbefore answering- no accept-backlog tuning, no per-IP connection limit, no global connection cap
Related, same class but separate resource: #63 (git upload-pack with no timeout/cap).
Fix direction:
- cap concurrent connections (e.g. semaphore of 64-256) and answer 503 immediately when exhausted
- keep the fixed ack delay for semantic uniformity, but do not let it pin a thread: either keep it (with the cap above) or use a small timer wheel; the cap is the simpler fix
- optionally lower
POST_READ_TIMEOUT_SECSand require the head within a shorter window than the body
Acceptance:
- N idle sockets beyond the cap get refused/closed, not thread-per-connection
- process thread count has a documented upper bound
-
a test/bench opens >cap sockets and asserts the server still answers
/
Uunknown ·
Correction: the cross-reference should point at #64 (upload-pack timeout/cap), not this issue. Same resource class: thread/subprocess exhaustion in serve.
Uunknown ·
Fixed in 80497982-9d71-46ca-a8aa-5f4ded049800 (see PR body): bounded 64 connections with immediate 503 + 10s head deadline (#63), 4 concurrent upload-pack runs with 120s timeout and temp-file streaming (#64), 5-minute full-map sweep + 100k key cap in RateLimiter (#65).