P4.1-001: 2s read timeout on accepted sockets (idle preconnect wedged the loop)

A browser speculative preconnection sends no bytes; the sequential
accept loop blocked in read() on it forever while real requests sat in
the backlog — LAN clients saw a dead server while curl (connect+send in
one shot) worked. SO_RCVTIMEO frees the loop. Regression case pinned in
tests/server_http.sx (fails 000 pre-fix, 200 post-fix).
This commit is contained in:
agra
2026-06-12 01:47:30 +03:00
parent 734c00fb98
commit 886b48630b
3 changed files with 31 additions and 0 deletions

View File

@@ -149,6 +149,18 @@ main :: () -> s32 {
process.assert(get_str(get_obj(bad, "error"), "code") == "download.unknown_object", "unknown digest names download.unknown_object");
print(" download ok\n");
// ── idle preconnect must not wedge the accept loop ────────────────
// Hold a connection open that never sends bytes (what a browser's
// speculative preconnect does) and require a real request to still be
// answered: the 2s read timeout must free the loop well inside curl's
// 5s budget. Pre-fix (no SO_RCVTIMEO) this curl times out with 000.
process.run("sh -c '(sleep 6 | nc 127.0.0.1 18792 > /dev/null 2>&1) &'");
process.run("sleep 0.3");
wc := process.run(concat(concat("curl -s -m 5 -o /dev/null -w '%{http_code}' ", BASE), "/healthz"));
process.assert(wc != null, "curl spawn failed (idle-conn case)");
process.assert(wc!.stdout == "200", "request must be served while an idle connection is held open");
print(" idle connection cannot wedge the loop\n");
// ── freshness: publish B while the server runs ────────────────────
rb := process.run(publish_cmd(path_join(MDIR, "b.json")));
process.assert(rb != null and rb!.exit_code == 0, "publish B must exit 0");