code wiki / (root) / nx_segopen_absent_gate.nx

nx_segopen_absent_gate.nx

buildroot/runtime/nx_segopen_absent_gate.nx

9860 B196 linesdepth 3pulls 4 transitivereach 0 importersview sourcekind gate/proof
docsdependenciesstructsconstsfunctions

about

nx_segopen_absent_gate.nx -- THE REFEREE FOR ss_open2's FAIL-SAFE SEGMENT ADMISSION (2026-09-02, debt 1788361379). WHY THIS GATE EXISTS, MEASURED: nishifamily.com/search was 503 for ~16h. The serving daemon's parent SIGSEGV'd inside the accept-path shard refresh, and the guard's respawn then SPUN 15.9h of user CPU inside ss_open2 with the listen port never opened (State R, voluntary ctxsw 8, nonvoluntary 26.1M). Its /proc maps held one manifest segment with its .idx mapped and NO .docs: ss_open2 sized that segment's live map from dsz (== 0, one page) but bounded the marks by the .post doc count, so the marks wrote past the page -- SIGSEGV when the next page was unmapped, silent table corruption and an endless probe when it was mapped. The fix makes an index-present/docs-absent row contribute NO live docs and ANNOUNCES it on stderr. IN-PROCESS over nx_seg_store.nx, deliberately: the subject is a library function, the fixture plane lives in /tmp/<gate>/ (never knowledge/store, which the segguard beat sweeps), and every outcome tooth is preceded by a fixture-reached-the-condition tooth so a setup failure cannot pass for a verdict. STATE, NOT MESSAGE: the live-map bytes of the handle are read directly (h[1 + 8*ns + s]), because a leaking or overflowing open answers the same bytes to every caller -- only the map can prove it. The segment NAME is read back from the manifest the writer produced, never recomputed from the id the gate asked for: ss_commit re-derives the id under the plane lock, so a leftover file from an earlier run would otherwise make the gate rename the wrong file and fail its own fixture tooth. PRE-FIX this gate reads RED on exactly the two load-bearing teeth (marks written for absent docs, no announce) and GREEN on every fixture tooth; POST-FIX it reads GREEN throughout. That asymmetry is the bite.

dependencies 3 imports · 0 importers

nx_seg_store.nx nx_syscalls.nx nx_gate_verdict.nx nx_segopen_absent_gate.nx

imports: nx_seg_store.nxnx_syscalls.nxnx_gate_verdict.nx

imported by: nobody (leaf or entry point)

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main gv_head gv_puts sys_write gv_ctr sys_mmap nxa_die sys_write ↻ sys_exit nxa_lock_take nxa_lock_addr sys_write ↻ nxa_lock_give nxa_lock_addr ↻ nxa_report_overrun sys_write ↻ nxa_dump_printable sys_write ↻ nxa_dump_sizes sys_write ↻ gv_subjects gv_puts ↻ gv_num sys_mmap ↻ sys_write ↻ sys_munmap gv_need gv_puts ↻ sys_mkdir sg_reset sys_mmap ↻ ss_cat ss_writefile sys_openat_wr sys_write ↻ sys_close sys_fsync ss_begin_cap sys_mmap ↻ sys_mmap ↻

structs

none

consts

26const SG_DIR: *u8 = "/tmp/nx_segopen_absent_gate"
27const SG_PREFIX: *u8 = "/tmp/nx_segopen_absent_gate/soa-"
28const SG_ERR1: *u8 = "/tmp/nx_segopen_absent_gate/stderr-control.txt"
29const SG_ERR2: *u8 = "/tmp/nx_segopen_absent_gate/stderr-absent.txt"
30const SG_MODE_DIR: i64 = 493 // 0755
31const SG_MODE_FILE: i64 = 420 // 0644
32const SG_DOCS: i64 = 12 // docs in the ONE fixture segment; every one must read live in the control
33const SG_SEGCAP: i64 = 65536
34const SG_KIND_LIVE: i64 = 1
35const SG_KEYCAP: i64 = 64
36const SG_VALCAP: i64 = 64
37const SG_PATHCAP: i64 = 512
38const SG_SAVED_FD: i64 = 20 // where fd 2 is parked while an open's stderr is captured
39const SG_SUBJECTS: i64 = 3 // opens driven: control, absent-docs, restored

functions

41func sg_key(out: *u8, i: i64) -> i64
called by 1: main calls 2: ss_catss_catn
50func sg_reset(prefix: *u8) -> i64
called by 1: main calls 3: sys_mmapss_catss_writefile
61func sg_marks(h: *i64, s: i64, n: i64) -> i64
called by 1: main
71func sg_seg_path(prefix: *u8, segname: *u8, suffix: *u8, out: *u8) -> i64
called by 1: main calls 1: ss_cat
79func sg_contains(hay: *u8, hn: i64, needle: *u8) -> i64
called by 1: main
95func sg_open_captured(prefix: *u8, errpath: *u8) -> *i64
105func main(argc: i64, argv: *i64) -> i64