distd: read timeout 2s -> 250ms (interim, PLAN-HTTPZ)

Each idle browser preconnect blocks the sequential accept loop for the
full SO_RCVTIMEO serially (measured: ~1.9s behind one, ~3.9s behind
two), so the timeout must stay well under human patience until the
readiness loop lands (PLAN-HTTPZ A1 retires the mechanism).
set_read_timeout takes milliseconds now.
This commit is contained in:
agra
2026-06-12 20:24:19 +03:00
parent 963a21596a
commit a6052bbb4c
2 changed files with 8 additions and 5 deletions

View File

@@ -1052,7 +1052,7 @@ run_server :: (store_dir: string, port: i64) -> !ServeErr {
while true {
client := sock.accept(fd, null, null);
if client < 0 { continue; }
http.set_read_timeout(client, 2);
http.set_read_timeout(client, 250);
gpa := GPA.init();
arena := Arena.init(xx gpa, 65536);

View File

@@ -80,12 +80,15 @@ Timeval :: struct {
pad: i32 = 0;
}
// Bound blocking reads on `fd` to `secs` seconds. A sequential accept
// Bound blocking reads on `fd` to `ms` milliseconds. A sequential accept
// loop needs this: browsers open speculative preconnections that never
// send bytes, and an unbounded read on one of those wedges the whole
// server while real requests sit in the backlog.
set_read_timeout :: (fd: i32, secs: i64) {
tv : Timeval = .{ tv_sec = secs };
// server while real requests sit in the backlog. Every idle socket costs
// the full timeout serially, so it must stay well under human patience;
// a LAN client delivers its request bytes within a few ms of connecting.
// (Retired by PLAN-HTTPZ A1, when the loop goes readiness-based.)
set_read_timeout :: (fd: i32, ms: i64) {
tv : Timeval = .{ tv_sec = ms / 1000, tv_usec = xx ((ms % 1000) * 1000) };
sock.setsockopt(fd, sock.SOL_SOCKET, SO_RCVTIMEO, xx @tv, 16);
}