code wiki / (root) / nx_segopen_absent_gate.nx

nx_segopen_absent_gate.nx source

↩ module page · 196 lines · 9860 B

1// nx_segopen_absent_gate.nx -- THE REFEREE FOR ss_open2's FAIL-SAFE SEGMENT ADMISSION (2026-09-02, debt 1788361379). 2// 3// WHY THIS GATE EXISTS, MEASURED: nishifamily.com/search was 503 for ~16h. The serving daemon's parent 4// SIGSEGV'd inside the accept-path shard refresh, and the guard's respawn then SPUN 15.9h of user CPU inside 5// ss_open2 with the listen port never opened (State R, voluntary ctxsw 8, nonvoluntary 26.1M). Its /proc maps 6// held one manifest segment with its .idx mapped and NO .docs: ss_open2 sized that segment's live map from 7// dsz (== 0, one page) but bounded the marks by the .post doc count, so the marks wrote past the page -- 8// SIGSEGV when the next page was unmapped, silent table corruption and an endless probe when it was mapped. 9// The fix makes an index-present/docs-absent row contribute NO live docs and ANNOUNCES it on stderr. 10// 11// IN-PROCESS over nx_seg_store.nx, deliberately: the subject is a library function, the fixture plane lives 12// in /tmp/<gate>/ (never knowledge/store, which the segguard beat sweeps), and every outcome tooth is 13// preceded by a fixture-reached-the-condition tooth so a setup failure cannot pass for a verdict. 14// STATE, NOT MESSAGE: the live-map bytes of the handle are read directly (h[1 + 8*ns + s]), because a 15// leaking or overflowing open answers the same bytes to every caller -- only the map can prove it. 16// The segment NAME is read back from the manifest the writer produced, never recomputed from the id the 17// gate asked for: ss_commit re-derives the id under the plane lock, so a leftover file from an earlier run 18// would otherwise make the gate rename the wrong file and fail its own fixture tooth. 19// PRE-FIX this gate reads RED on exactly the two load-bearing teeth (marks written for absent docs, no 20// announce) and GREEN on every fixture tooth; POST-FIX it reads GREEN throughout. That asymmetry is the bite. 21 22import "nx_seg_store.nx" 23import "nx_syscalls.nx" 24import "nx_gate_verdict.nx" 25 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 40 41func sg_key(out: *u8, i: i64) -> i64 { 42 // "doc:<i+1>" NUL-terminated -- the ONLY key shape ss_doc_count counts, so the index-side census is real 43 var o: i64 = 0 44 o = ss_cat(out, o, "doc:" as *u8) 45 o = ss_catn(out, o, i + 1) 46 out[o] = 0 as u8 47 return o 48} 49 50func sg_reset(prefix: *u8) -> i64 { 51 let mf: *u8 = sys_mmap(SG_PATHCAP) 52 var o: i64 = ss_cat(mf, 0, prefix) 53 o = ss_cat(mf, o, "manifest.txt" as *u8) 54 mf[o] = 0 as u8 55 let e: *u8 = sys_mmap(16) 56 ss_writefile(mf, e, 0) 57 return 0 58} 59 60// count live-map marks for segment s over the first n doc indexes -- the STATE the serve path reads 61func sg_marks(h: *i64, s: i64, n: i64) -> i64 { 62 let ns: i64 = h[0] 63 let lm: *u8 = h[1 + 8 * ns + s] as *u8 64 if (lm as i64) == 0 { return 0 - 1 } 65 var c: i64 = 0 66 var i: i64 = 0 67 while i < n { if lm[i] == (1 as u8) { c = c + 1 } i = i + 1 } 68 return c 69} 70 71func sg_seg_path(prefix: *u8, segname: *u8, suffix: *u8, out: *u8) -> i64 { 72 var o: i64 = ss_cat(out, 0, prefix) 73 o = ss_cat(out, o, segname) 74 o = ss_cat(out, o, suffix) 75 out[o] = 0 as u8 76 return o 77} 78 79func sg_contains(hay: *u8, hn: i64, needle: *u8) -> i64 { 80 var nn: i64 = 0 81 while needle[nn] != (0 as u8) { nn = nn + 1 } 82 if hn < nn { return 0 } 83 var i: i64 = 0 84 while i + nn <= hn { 85 var j: i64 = 0 86 var ok: i64 = 1 87 while j < nn { if hay[i + j] != needle[j] { ok = 0; break } j = j + 1 } 88 if ok == 1 { return 1 } 89 i = i + 1 90 } 91 return 0 92} 93 94// run ONE ss_open2 with fd 2 redirected to errpath, restore fd 2, return the handle 95func sg_open_captured(prefix: *u8, errpath: *u8) -> *i64 { 96 let efd: i64 = sys_openat_wr(errpath, SG_MODE_FILE) 97 sys_dup3(2, SG_SAVED_FD, 0) 98 if efd >= 0 { sys_dup3(efd, 2, 0) } 99 let h: *i64 = ss_open2(prefix, 1) 100 sys_dup3(SG_SAVED_FD, 2, 0) 101 if efd >= 0 { sys_close(efd) } 102 return h 103} 104 105func main(argc: i64, argv: *i64) -> i64 { 106 gv_head("nx_segopen_absent_gate -- ss_open2 fail-safe admission of an index-present / docs-absent segment" as *u8) 107 let ctr: *i64 = gv_ctr() 108 gv_subjects("shard opens driven" as *u8, SG_SUBJECTS, ctr) 109 110 sys_mkdir(SG_DIR, SG_MODE_DIR) 111 sg_reset(SG_PREFIX) 112 113 // ---- FIXTURE: one segment, SG_DOCS live docs, committed through the real writer ---- 114 let wr: *i64 = ss_begin_cap(SG_SEGCAP) 115 let key: *u8 = sys_mmap(SG_KEYCAP) 116 let val: *u8 = sys_mmap(SG_VALCAP) 117 var i: i64 = 0 118 while i < SG_DOCS { 119 sg_key(key, i) 120 var vn: i64 = ss_cat(val, 0, "live doc number " as *u8) 121 vn = ss_catn(val, vn, i + 1) 122 val[vn] = 0 as u8 123 ss_add(wr, SG_KIND_LIVE, key, val, vn) 124 i = i + 1 125 } 126 let crc: i64 = ss_commit(SG_PREFIX, wr, ss_next_segid(SG_PREFIX)) 127 gv_check("fixture-setup-commit-succeeded" as *u8, crc == 0, ctr) 128 // the segment NAME comes from the manifest the writer produced (ss_commit re-derives the id under lock) 129 let sp: *i64 = sys_mmap(8) as *i64 130 let ns0: i64 = ss_manifest_dyn(SG_PREFIX, sp) 131 let segs0: *i64 = sp[0] as *i64 132 gv_check("fixture-setup-manifest-names-exactly-one-segment" as *u8, ns0 == 1, ctr) 133 let segname: *u8 = sys_mmap(SG_KEYCAP) 134 var sno: i64 = 0 135 if ns0 >= 1 { sno = ss_cat(segname, 0, segs0[0] as *u8) } 136 segname[sno] = 0 as u8 137 if ns0 >= 1 { ss_manifest_free(segs0, ns0) } 138 var opened: i64 = 0 139 140 // ---- POSITIVE CONTROL: docs present -> every doc live, nothing announced ---- 141 let h1: *i64 = sg_open_captured(SG_PREFIX, SG_ERR1) 142 opened = opened + 1 143 gv_check("control-open-sees-exactly-one-segment" as *u8, h1[0] == 1, ctr) 144 gv_check("control-docs-loaded-nonzero" as *u8, h1[4] > 0, ctr) 145 gv_check("control-index-loaded" as *u8, h1[2] >= 8, ctr) 146 gv_check("control-post-blob-loaded" as *u8, h1[8] >= 8, ctr) 147 gv_check("control-every-doc-marked-live" as *u8, sg_marks(h1, 0, SG_DOCS) == SG_DOCS, ctr) 148 gv_check("control-index-census-counts-every-doc" as *u8, ss_doc_count(h1) == SG_DOCS, ctr) 149 let e1n: *i64 = sys_mmap(16) as *i64 150 let e1: *u8 = ss_readall(SG_ERR1, e1n) 151 var e1len: i64 = e1n[0] 152 if e1len < 0 { e1len = 0 } 153 gv_check("neg-control-a-healthy-open-announces-no-skip" as *u8, sg_contains(e1, e1len, "SSOPEN SKIP" as *u8) == 0, ctr) 154 ss_close(h1) 155 156 // ---- REACH THE CONDITION: the manifest still names the segment, its .docs is gone, its .idx stays ---- 157 let pdocs: *u8 = sys_mmap(SG_PATHCAP) 158 let phid: *u8 = sys_mmap(SG_PATHCAP) 159 sg_seg_path(SG_PREFIX, segname, ".docs" as *u8, pdocs) 160 sg_seg_path(SG_PREFIX, segname, ".docs.hidden" as *u8, phid) 161 let mrc: i64 = sys_renameat(pdocs, phid) 162 gv_check("fixture-reached-condition-docs-renamed-away" as *u8, mrc == 0, ctr) 163 164 let h2: *i64 = sg_open_captured(SG_PREFIX, SG_ERR2) 165 opened = opened + 1 166 // If the open crashed or spun, this line is never reached and the runner's timeout is the RED. 167 gv_check("absent-docs-open-returns-a-handle" as *u8, (h2 as i64) != 0, ctr) 168 gv_check("absent-docs-handle-still-names-the-segment" as *u8, h2[0] == 1, ctr) 169 // ss_loadfile reports an absent file as ss_readall's -1 and an empty one as 0: both are "did not load" 170 gv_check("fixture-reached-condition-docs-size-not-positive" as *u8, h2[4] <= 0, ctr) 171 gv_check("fixture-reached-condition-index-still-loaded" as *u8, h2[2] >= 8, ctr) 172 gv_check("fixture-reached-condition-post-blob-still-loaded" as *u8, h2[8] >= 8, ctr) 173 // THE LOAD-BEARING TOOTH: with no docs behind it, the segment must mark NOTHING live. Pre-fix the marks 174 // are written anyway (bounded by the .post count, not by the docs) -- for a 12-doc fixture they land 175 // inside the one page and read 12; on the 5.3M-entry web shard they landed past it. 176 gv_check("absent-docs-segment-marks-NO-doc-live" as *u8, sg_marks(h2, 0, SG_DOCS) == 0, ctr) 177 gv_check("index-census-still-sees-the-docs-so-the-skip-was-a-decision" as *u8, ss_doc_count(h2) == SG_DOCS, ctr) 178 let e2n: *i64 = sys_mmap(16) as *i64 179 let e2: *u8 = ss_readall(SG_ERR2, e2n) 180 var e2len: i64 = e2n[0] 181 if e2len < 0 { e2len = 0 } 182 gv_check("skip-is-ANNOUNCED-on-stderr" as *u8, sg_contains(e2, e2len, "SSOPEN SKIP seg=" as *u8) == 1, ctr) 183 gv_check("announce-names-the-condition" as *u8, sg_contains(e2, e2len, "docs-absent" as *u8) == 1, ctr) 184 ss_close(h2) 185 186 // ---- RESTORE and re-open: the marks return, proving the state was the FILE, not the code ---- 187 let rrc: i64 = sys_renameat(phid, pdocs) 188 gv_check("fixture-restore-docs-renamed-back" as *u8, rrc == 0, ctr) 189 let h3: *i64 = ss_open2(SG_PREFIX, 1) 190 opened = opened + 1 191 gv_check("restored-docs-every-doc-marked-live-again" as *u8, sg_marks(h3, 0, SG_DOCS) == SG_DOCS, ctr) 192 ss_close(h3) 193 194 gv_check("denominator-every-declared-open-was-driven" as *u8, opened == SG_SUBJECTS, ctr) 195 return gv_verdict("nx_segopen_absent_gate" as *u8, ctr, "in-process over nx_seg_store ss_open2: an index-present / docs-absent manifest row contributes no live docs, is announced on stderr, and neither crashes nor spins the open" as *u8) 196}