nx_fetch_bounded.nx
buildroot/runtime/nx_fetch_bounded.nx
about
nx_fetch_bounded.nx -- bounded + timed streaming fetch drain (RES-R7).
ROOT CAUSE this organ fixes:
The existing drains silently lose data and can hang forever.
- nx_browse_text.nx:55 br_drain : fills to `cap`, returns `off`,
gives the caller NO way to tell "exactly cap" from "truncated at
cap" -- silent truncation. No read timeout -> a stalled peer
blocks sys_read forever.
- nx_fetch_unit.nx:172 : `if blen > cap { blen = cap }`
-- a SILENT clamp: oversize bodies are quietly chopped, length
lost. No per-fetch timeout.
THE FIX (mirrors the h2 large-page streaming-consume contract,
h2_stream_consume): count the wire length UNBOUNDED, copy only up to
`cap`, and report BOTH an explicit status code AND the full counted
length. Never silently clamp. Enforce a wall-clock deadline via
sys_poll so a stalled read returns within the budget with a timeout
code instead of hanging the conductor.
SINGLE RESPONSIBILITY: bounded+timed streaming drain over ANY readable
fd. Composes only nx_syscalls.nx primitives (sys_poll, sys_read,
sys_now_us, sys_mmap) -- fully sovereign, no network/TLS/gcc. The
existing br_drain / nx_fetch_staged are NOT modified (additive-only);
callers migrate to fb_drain_bounded in a later rung.
build/placement: harness resolves `nx_fetch_bounded` ->
runtime/nx_fetch_bounded.nx (2nd fallback).
expect_exit: 0
license_tier: ORIGINAL
dependencies 1 imports · 1 importers
imports: nx_syscalls.nx
imported by: _fetch_bounded_gate.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 37 | const FB_OK: i64 = 0 // fully consumed within cap and before deadline |
| 38 | const FB_OVERFLOW: i64 = 0 - 70 // body exceeded cap; full length still counted (no silent trunc) |
| 39 | const FB_TIMEOUT: i64 = 0 - 71 // deadline hit before EOF (slow / stalled peer) |
| 40 | const FB_READ_ERR: i64 = 0 - 72 // sys_read returned < 0 (not EOF) |
| 43 | const FB_DEFAULT_TIMEOUT_MS: i64 = 30000 // per-fetch wall budget when caller passes <= 0 |
| 44 | const FB_READ_SLICE: i64 = 65536 // streaming read granularity (compact-as-you-go) |
| 45 | const FB_POLLIN: i64 = 1 // POLLIN event mask (matches nx_syscalls POLLIN) |
functions
| 49 | func fb_pfd_set(pf: *u8, fd: i64, events: i64) -> i64 called by 1: fb_wait_readable |
| 67 | func fb_wait_readable(fd: i64, deadline_us: i64) -> i64 |
| 92 | func fb_drain_bounded(fd: i64, out: *u8, cap: i64, timeout_ms: i64, counted_out: *i64) -> i64 |
| 142 | func main() -> i64 |