nx_http_probe_gate.nx source
↩ module page · 428 lines · 21262 B
1// nx_http_probe_gate.nx -- THE REFEREE FOR nx_http_probe. Hermetic, in-process, no external service.
2//
3// WHAT IT HAS TO PROVE, AND WHY THE OBVIOUS GATE WOULD NOT PROVE IT. The organ under test replaces a
4// cron one-liner whose ONLY defect was that it failed SILENTLY: the row fired, the command did not run,
5// all output was discarded, and the capability-plane watch went stale at 10.9x its budget with nobody
6// able to name which link broke. A gate that only asks "does a healthy endpoint return 0" would pass a
7// probe that ALSO returns 0 for a dead one, and a gate that only reads exit codes would pass a probe
8// that stamps the heartbeat on a FAILING run -- which is the same blindness wearing a green badge.
9// So every failure fixture asserts TWO things: the NAMED exit code, and THE ABSENCE OF THE HEARTBEAT.
10// **** THE STAMP IS THE THING THE WATCHER BELIEVES. ASSERTING ITS ABSENCE IS THE TOOTH. ****
11//
12// THE POSITIVE CONTROL IS NOT DECORATION. A guard that refuses everything passes every negative test,
13// and four SSRF deny-tests once went green over a wholly broken guard for exactly that reason. T1-T4
14// are the input that MUST be accepted, so an always-fail probe cannot score.
15//
16// THE ABSENCE FIXTURES REUSE THE PATH THE POSITIVE CONTROL JUST WROTE. A fixture that asserts "no file
17// appeared at some path" is vacuous if nothing could ever have appeared there. T1/T2 prove this organ
18// writes THIS EXACT PATH; the failing runs then unlink it and prove it stays gone.
19//
20// FIXTURES ARE ASSEMBLED AT RUNTIME, NOT WRITTEN AS LITERALS. A source-scanning detector finds its own
21// fixture, and the estate has paid for that twice. The JSON marker is built from a quote byte, so the
22// needle and the body it lives in come from ONE code path and cannot drift apart.
23//
24// SCRATCH LIVES IN /tmp/nx_http_probe_gate/, NEVER the production tree: a gate that shares a fixture
25// with a production beat reports on the FIXTURE, not on the code (nx_gate_fixture_ratchet_gate).
26// Setup creates and clears; there is no teardown, because a teardown does not run when a run crashes.
27//
28// PORTS ARE PROVEN FREE BY BINDING THEM, NEVER ASSUMED. A probe port you did not verify free is not a
29// control, it is a second instance. If any port is taken the gate SKIPs -- "I could not look" is not
30// "it is broken".
31//
32// expect_exit: 0 license_tier: ORIGINAL No hw writes (Rule 26).
33import "nx_syscalls.nx"
34import "nx_clock.nx"
35import "nx_gate_verdict.nx"
36import "nx_http_probe_lib.nx"
37
38const HPG_PORT_OK: i64 = 19791
39const HPG_PORT_500: i64 = 19792
40const HPG_PORT_HANG: i64 = 19793
41const HPG_PORT_CLOSED: i64 = 19794
42const HPG_BACKLOG: i64 = 16
43const HPG_ADDR_BYTES: i64 = 16
44const HPG_BUF: i64 = 8192
45const HPG_DQUOTE: i64 = 34
46const HPG_DIR_MODE: i64 = 493
47// hp_run's last argument controls the PER-LEG TRACE lines only. It can never silence the verdict --
48// the subject has no quiet mode by design -- so both settings still announce every outcome.
49const HPG_TRACE_OFF: i64 = 0
50const HPG_TRACE_ON: i64 = 1
51const HPG_NS_PER_MS: i64 = 1000000
52const HPG_BAD_CODE: i64 = 999
53// One second is enough for a loopback fixture and keeps the whole gate under a few seconds. The hang
54// fixture is the only one that spends it, and it spends it exactly once.
55const HPG_BUDGET_SEC: i64 = 1
56// The hang fixture must come back inside a WINDOW, not merely "eventually". The floor catches a probe
57// that never actually waited (a bail-out-instantly false pass); the ceiling is what fails a probe that
58// inherited the unbounded read this organ exists to replace -- that one would never return at all.
59const HPG_HANG_MIN_MS: i64 = 500
60const HPG_HANG_MAX_MS: i64 = 3000
61// The stamp epoch must land inside the run's own window. A hard-coded `ts=0`, or a fossil left by an
62// earlier run, fails this even though the file exists and parses.
63const HPG_EPOCH_SLACK: i64 = 120
64// fd numbers for the stderr-capture tooth. 2 is stderr by definition; the save slot is any fd this
65// process demonstrably does not use, and dup3 refuses oldfd==newfd so it can never alias stderr.
66const HPG_FD_STDERR: i64 = 2
67const HPG_FD_ERRSAVE: i64 = 200
68
69func hpg_cat(d: *u8, o: i64, s: *u8) -> i64 {
70 var i: i64 = 0
71 var p: i64 = o
72 while s[i] != (0 as u8) { d[p] = s[i]; p = p + 1; i = i + 1 }
73 return p
74}
75func hpg_catc(d: *u8, o: i64, c: i64) -> i64 { d[o] = c as u8; return o + 1 }
76
77// sockaddr_in for 127.0.0.1:<port>, via the SAME packer the subject uses.
78func hpg_sa(port: i64) -> *u8 {
79 let s: *u8 = sys_mmap(HPG_ADDR_BYTES)
80 nx_http_client_sockaddr_ipv4(s, 127, 0, 0, 1, port)
81 return s
82}
83
84// Bind+listen on a loopback port. Returns the listening fd, or -1 -- and -1 means THE PORT WAS TAKEN,
85// which is a precondition failure, not a verdict about the subject.
86func hpg_listen(port: i64) -> i64 {
87 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
88 if fd < 0 { return 0 - 1 }
89 let opt: *i64 = sys_mmap(8) as *i64
90 opt[0] = 1
91 sys_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, opt as *u8, 4)
92 let sa: *u8 = hpg_sa(port)
93 if sys_bind(fd, sa, HPG_ADDR_BYTES) < 0 { sys_close(fd); return 0 - 1 }
94 if sys_listen(fd, HPG_BACKLOG) < 0 { sys_close(fd); return 0 - 1 }
95 return fd
96}
97
98// Fork a one-shot responder on an ALREADY-LISTENING fd. Binding in the PARENT before the fork removes
99// the classic fixture race entirely: the port is listening before the child exists, so the probe can
100// never arrive before the server is up. The child reads the request first so the peer never sees a RST.
101func hpg_respond_once(lfd: i64, resp: *u8, rlen: i64) -> i64 {
102 let pid: i64 = sys_fork()
103 if pid == 0 {
104 let cfd: i64 = sys_accept(lfd)
105 if cfd >= 0 {
106 let rq: *u8 = sys_mmap(HPG_BUF)
107 sys_read(cfd, rq, HPG_BUF)
108 sys_write(cfd, resp, rlen)
109 sys_close(cfd)
110 }
111 sys_exit(0)
112 }
113 return pid
114}
115
116func hpg_reap(pid: i64) -> i64 {
117 if pid <= 0 { return 0 }
118 let st: *i64 = sys_mmap(8) as *i64
119 sys_wait4(pid, st, 0)
120 sys_munmap(st as *u8, 8)
121 return 0
122}
123
124func hpg_exists(path: *u8) -> i64 {
125 let fd: i64 = sys_openat_rd(path)
126 if fd < 0 { return 0 }
127 sys_close(fd)
128 return 1
129}
130func hpg_slurp(path: *u8, dst: *u8, cap: i64) -> i64 {
131 let fd: i64 = sys_openat_rd(path)
132 if fd < 0 { return 0 - 1 }
133 let n: i64 = sys_read(fd, dst, cap - 1)
134 sys_close(fd)
135 if n < 0 { return 0 - 1 }
136 dst[n] = 0 as u8
137 return n
138}
139
140// THE MARKER AND THE BODY COME FROM ONE PLACE. dst gets "secure":<word> with real double quotes,
141// assembled from a byte so no literal in this source can be mistaken for the thing being detected.
142func hpg_marker(dst: *u8, word: *u8) -> i64 {
143 var o: i64 = 0
144 o = hpg_catc(dst, o, HPG_DQUOTE)
145 o = hpg_cat(dst, o, "secure" as *u8)
146 o = hpg_catc(dst, o, HPG_DQUOTE)
147 o = hpg_cat(dst, o, ":" as *u8)
148 o = hpg_cat(dst, o, word)
149 dst[o] = 0 as u8
150 return o
151}
152
153func hpg_response(dst: *u8, statusline: *u8, marker: *u8) -> i64 {
154 var o: i64 = 0
155 o = hpg_cat(dst, o, statusline)
156 o = hpg_cat(dst, o, "Content-Type: application/json\r\nConnection: close\r\n\r\n" as *u8)
157 o = hpg_cat(dst, o, "{" as *u8)
158 o = hpg_cat(dst, o, marker)
159 o = hpg_cat(dst, o, "}" as *u8)
160 dst[o] = 0 as u8
161 return o
162}
163
164func main(argc: i64, argv: *i64) -> i64 {
165 gv_head("nx_http_probe_gate -- the replacement for the silent curl cron row must be UNABLE to fail silently" as *u8)
166 let ctr: *i64 = gv_ctr()
167
168 // ---- SETUP. Idempotent: create the dir every run, clear the stamp before every use. -----------
169 let dir: *u8 = "/tmp/nx_http_probe_gate" as *u8
170 sys_mkdir(dir, HPG_DIR_MODE)
171 let stamp: *u8 = "/tmp/nx_http_probe_gate/shared.stamp" as *u8
172 let badstamp: *u8 = "/tmp/nx_http_probe_gate/no-such-subdir/x.stamp" as *u8
173 sys_unlinkat(stamp)
174
175 // PORT_CLOSED is proven FREE by binding it and then closing it, so "connect refused" is a fact about
176 // the fixture and not a guess about what else might be running on this box.
177 let closed_probe: i64 = hpg_listen(HPG_PORT_CLOSED)
178 var closed_free: i64 = 0
179 if closed_probe >= 0 { closed_free = 1; sys_close(closed_probe) }
180
181 let l_ok: i64 = hpg_listen(HPG_PORT_OK)
182 let l_500: i64 = hpg_listen(HPG_PORT_500)
183 let l_hang: i64 = hpg_listen(HPG_PORT_HANG)
184 var ports_ok: i64 = 0
185 if l_ok >= 0 { if l_500 >= 0 { if l_hang >= 0 { if closed_free == 1 { ports_ok = 1 } } } }
186 gv_need("four loopback probe ports proven FREE by binding them (never assumed)" as *u8, ports_ok, ctr)
187
188 // Writability of the scratch dir is a precondition too: an unwritable /tmp makes every stamp tooth
189 // report on the environment rather than on the organ, in the same word.
190 var dirw: i64 = 0
191 let probe_fd: i64 = sys_openat_wr("/tmp/nx_http_probe_gate/.writecheck" as *u8, HP_MODE_0644)
192 if probe_fd >= 0 { dirw = 1; sys_close(probe_fd) }
193 gv_need("fixture dir /tmp/nx_http_probe_gate is writable" as *u8, dirw, ctr)
194
195 // STOP HERE IF WE CANNOT LOOK. Running the teeth against an unbuildable fixture would file
196 // environment failures as findings about the subject, in the same word -- the exact thing gv_need
197 // exists to prevent. gv_verdict with preconditions missing and nothing failed returns 3 = SKIP.
198 var can_run: i64 = 0
199 if ports_ok == 1 { if dirw == 1 { can_run = 1 } }
200 if can_run == 0 {
201 let rcskip: i64 = gv_verdict("HTTP-PROBE-GATE" as *u8, ctr, "unreachable" as *u8)
202 sys_exit(rcskip)
203 return rcskip
204 }
205
206 let need_true: *u8 = sys_mmap(HPG_BUF)
207 let need_false: *u8 = sys_mmap(HPG_BUF)
208 hpg_marker(need_true, "true" as *u8)
209 hpg_marker(need_false, "false" as *u8)
210
211 let r200: *u8 = sys_mmap(HPG_BUF)
212 let r500: *u8 = sys_mmap(HPG_BUF)
213 let n200: i64 = hpg_response(r200, "HTTP/1.1 200 OK\r\n" as *u8, need_true)
214 // THE 500 FIXTURE CARRIES THE *MATCHING* MARKER ON PURPOSE. If the status check were skipped, or
215 // ran after the pattern check, this run would come back clean -- so this tooth isolates the status
216 // conjunct instead of letting two signals pass as one.
217 let n500: i64 = hpg_response(r500, "HTTP/1.1 500 Internal Server Error\r\n" as *u8, need_true)
218
219 let sb: *u8 = sys_mmap(HPG_BUF)
220
221 // ================= T1-T4 POSITIVE CONTROL: the input that MUST be accepted ====================
222 let t_before: i64 = sys_now_realtime_sec()
223 let p1: i64 = hpg_respond_once(l_ok, r200, n200)
224 let rc_ok: i64 = hp_run(HPG_PORT_OK, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, stamp, HPG_TRACE_ON)
225 hpg_reap(p1)
226 let t_after: i64 = sys_now_realtime_sec()
227
228 var c1: i64 = 0
229 if rc_ok == HP_EXIT_OK { c1 = 1 }
230 gv_check("pos-control-healthy-2xx-endpoint-with-the-marker-exits-0" as *u8, c1, ctr)
231
232 let stamped: i64 = hpg_exists(stamp)
233 gv_check("pos-control-a-clean-run-WRITES-the-heartbeat" as *u8, stamped, ctr)
234
235 // THE MARKER IS BOUND ONCE AND ITS LENGTH IS DERIVED. A hand-counted 3 beside "ts=" is a second copy
236 // of that literal's shape, and the two drift silently: change the marker, forget the number, and the
237 // parser reads the wrong window while still compiling and still appearing to work.
238 let sn: i64 = hpg_slurp(stamp, sb, HPG_BUF)
239 let tsmark: *u8 = "ts=" as *u8
240 let tsl: i64 = hp_strlen(tsmark)
241 var c3: i64 = 0
242 if sn > tsl {
243 c3 = 1
244 var m: i64 = 0
245 while m < tsl { if sb[m] != tsmark[m] { c3 = 0 } m = m + 1 }
246 }
247 gv_check("heartbeat-marker-is-the-one-nx_cron_watch-actually-parses" as *u8, c3, ctr)
248
249 var stamped_ts: i64 = 0 - 1
250 if sn > tsl { stamped_ts = hp_atoi(sb, tsl, sn - tsl) }
251 var c4: i64 = 0
252 if stamped_ts >= t_before - HPG_EPOCH_SLACK {
253 if stamped_ts <= t_after + HPG_EPOCH_SLACK { c4 = 1 }
254 }
255 gv_puts(" stamp epoch=" as *u8); gv_num(stamped_ts)
256 gv_puts(" window=[" as *u8); gv_num(t_before); gv_puts("," as *u8); gv_num(t_after); gv_puts("]\n" as *u8)
257 gv_check("heartbeat-carries-THIS-run-s-epoch-not-zero-and-not-a-fossil" as *u8, c4, ctr)
258
259 // ================= T5-T6 the exact bug being fixed: a MISSING pattern ==========================
260 // The path below is the one T2 just proved this organ can write, so its absence here is a fact
261 // about the failing run and not about an unwritable fixture.
262 sys_unlinkat(stamp)
263 let p2: i64 = hpg_respond_once(l_ok, r200, n200)
264 let rc_pat: i64 = hp_run(HPG_PORT_OK, "/api/cap/status" as *u8, need_false, HPG_BUDGET_SEC, stamp, HPG_TRACE_OFF)
265 hpg_reap(p2)
266 var c5: i64 = 0
267 if rc_pat == HP_EXIT_PATTERN_ABSENT { c5 = 1 }
268 gv_check("neg-control-live-endpoint-WITHOUT-the-marker-exits-3-pattern-absent" as *u8, c5, ctr)
269 var c6: i64 = 0
270 if hpg_exists(stamp) == 0 { c6 = 1 }
271 gv_check("neg-control-pattern-absent-leaves-NO-heartbeat-so-the-watch-goes-STALE" as *u8, c6, ctr)
272
273 // ================= T7-T8 status conjunct, isolated ============================================
274 sys_unlinkat(stamp)
275 let p3: i64 = hpg_respond_once(l_500, r500, n500)
276 let rc_500: i64 = hp_run(HPG_PORT_500, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, stamp, HPG_TRACE_OFF)
277 hpg_reap(p3)
278 var c7: i64 = 0
279 if rc_500 == HP_EXIT_STATUS_NOT_2XX { c7 = 1 }
280 gv_check("neg-control-500-with-a-MATCHING-marker-still-exits-4-status-not-2xx" as *u8, c7, ctr)
281 var c8: i64 = 0
282 if hpg_exists(stamp) == 0 { c8 = 1 }
283 gv_check("neg-control-non-2xx-leaves-NO-heartbeat" as *u8, c8, ctr)
284
285 // ================= T9-T10 nothing listening ===================================================
286 sys_unlinkat(stamp)
287 let rc_conn: i64 = hp_run(HPG_PORT_CLOSED, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, stamp, HPG_TRACE_OFF)
288 var c9: i64 = 0
289 if rc_conn == HP_EXIT_CONNECT_FAILED { c9 = 1 }
290 gv_check("neg-control-unreachable-endpoint-exits-2-connect-failed-not-3-not-4" as *u8, c9, ctr)
291 var c10: i64 = 0
292 if hpg_exists(stamp) == 0 { c10 = 1 }
293 gv_check("neg-control-unreachable-endpoint-leaves-NO-heartbeat" as *u8, c10, ctr)
294
295 // ================= T11-T13 ACCEPTED THEN SILENT -- the 2026-08-06 shape =======================
296 // A listening socket with nobody accepting still completes the TCP handshake out of the backlog, so
297 // connect() SUCCEEDS and the response never comes. That is a wedged daemon, and it is the case an
298 // unbounded read loop can never report -- it parks forever and a */5 beat piles up processes.
299 sys_unlinkat(stamp)
300 let h0: i64 = nx_clock_monotonic_ns()
301 let rc_hang: i64 = hp_run(HPG_PORT_HANG, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, stamp, HPG_TRACE_OFF)
302 let h1: i64 = nx_clock_monotonic_ns()
303 var hel: i64 = 0 - 1
304 if h0 > 0 { if h1 > 0 { hel = (h1 - h0) / HPG_NS_PER_MS } }
305 var c11: i64 = 0
306 if rc_hang == HP_EXIT_RECV_TIMEOUT { c11 = 1 }
307 gv_check("neg-control-accepted-but-silent-endpoint-exits-6-recv-timeout" as *u8, c11, ctr)
308 var c12: i64 = 0
309 if hpg_exists(stamp) == 0 { c12 = 1 }
310 gv_check("neg-control-recv-timeout-leaves-NO-heartbeat" as *u8, c12, ctr)
311 gv_puts(" wedged-endpoint probe returned after " as *u8); gv_num(hel)
312 gv_puts(" ms (an unbounded read never returns at all)\n" as *u8)
313 var c13: i64 = 0
314 if hel >= HPG_HANG_MIN_MS { if hel <= HPG_HANG_MAX_MS { c13 = 1 } }
315 gv_check("the-read-leg-is-BOUNDED-measured-in-ms-not-taken-on-the-return-code-s-word" as *u8, c13, ctr)
316
317 // ================= T14 a stamp that CANNOT be written must say so =============================
318 let p4: i64 = hpg_respond_once(l_ok, r200, n200)
319 let rc_wr: i64 = hp_run(HPG_PORT_OK, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, badstamp, HPG_TRACE_OFF)
320 hpg_reap(p4)
321 var c14: i64 = 0
322 if rc_wr == HP_EXIT_STAMP_WRITE_FAILED { c14 = 1 }
323 gv_check("neg-control-an-unwritable-heartbeat-path-exits-5-instead-of-a-silent-no-op" as *u8, c14, ctr)
324
325 // ================= T15 ANTI-VACUITY: distinct outcomes, not one bucket ========================
326 // The trivial wrong implementation this kills is the one that collapses every failure into a single
327 // code -- which is what the curl row did (it had exactly one observable outcome: nothing).
328 var c15: i64 = 1
329 if rc_ok == rc_pat { c15 = 0 }
330 if rc_ok == rc_500 { c15 = 0 }
331 if rc_ok == rc_conn { c15 = 0 }
332 if rc_ok == rc_hang { c15 = 0 }
333 if rc_ok == rc_wr { c15 = 0 }
334 if rc_pat == rc_500 { c15 = 0 }
335 if rc_pat == rc_conn { c15 = 0 }
336 if rc_pat == rc_hang { c15 = 0 }
337 if rc_pat == rc_wr { c15 = 0 }
338 if rc_500 == rc_conn { c15 = 0 }
339 if rc_500 == rc_hang { c15 = 0 }
340 if rc_500 == rc_wr { c15 = 0 }
341 if rc_conn == rc_hang { c15 = 0 }
342 if rc_conn == rc_wr { c15 = 0 }
343 if rc_hang == rc_wr { c15 = 0 }
344 gv_check("anti-vacuity-six-different-conditions-produced-six-pairwise-distinct-exit-codes" as *u8, c15, ctr)
345
346 // ================= T16-T17 every code NAMES a reason, and only the unknown one says unknown ====
347 var c16: i64 = 1
348 var i: i64 = 0
349 while i <= HP_EXIT_NOT_HTTP {
350 if hp_streq(hp_reason(i), "unknown" as *u8) == 1 { c16 = 0 }
351 var j: i64 = i + 1
352 while j <= HP_EXIT_NOT_HTTP {
353 if hp_streq(hp_reason(i), hp_reason(j)) == 1 { c16 = 0 }
354 j = j + 1
355 }
356 i = i + 1
357 }
358 gv_check("every-declared-exit-code-carries-its-own-distinct-named-reason" as *u8, c16, ctr)
359 var c17: i64 = 0
360 if hp_streq(hp_reason(HPG_BAD_CODE), "unknown" as *u8) == 1 { c17 = 1 }
361 gv_check("neg-control-an-UNDECLARED-code-reports-unknown-rather-than-borrowing-a-real-reason" as *u8, c17, ctr)
362
363 // ================= T18-T19 the status parser is derived, and it refuses non-HTTP ==============
364 let synth: *u8 = sys_mmap(HPG_BUF)
365 var so: i64 = hpg_cat(synth, 0, "HTTP/1.0 204 No Content\r\n\r\n" as *u8)
366 var c18: i64 = 0
367 if hp_status_of(synth, so) == 204 { c18 = 1 }
368 gv_check("status-parse-is-derived-from-the-prefix-so-it-also-reads-HTTP-1-0" as *u8, c18, ctr)
369 let junk: *u8 = sys_mmap(HPG_BUF)
370 let jo: i64 = hpg_cat(junk, 0, "SSH-2.0-OpenSSH_9.2\r\n" as *u8)
371 var c19: i64 = 0
372 if hp_status_of(junk, jo) < 0 { c19 = 1 }
373 gv_check("neg-control-a-non-HTTP-reply-is-REFUSED-not-parsed-into-a-plausible-number" as *u8, c19, ctr)
374
375 // ================= T20 THE STDERR ANNOUNCE, WHICH IS THE WHOLE POINT ==========================
376 // The retired cron row sent stdout to a log and its own failure to nowhere. A replacement whose
377 // failure is visible ONLY to a caller who kept stdout inherits that defect exactly. So: rebind fd 2
378 // to a file, run one FAILING and one CLEAN fixture through it, and require the marker to appear for
379 // the first and NOT for the second. gv_bite scores both directions at once, because a channel that
380 // shouts on every run is as useless as one that never shouts.
381 let errcap: *u8 = "/tmp/nx_http_probe_gate/stderr.cap" as *u8
382 let errcap2: *u8 = "/tmp/nx_http_probe_gate/stderr2.cap" as *u8
383 sys_unlinkat(errcap)
384 sys_unlinkat(errcap2)
385 // gv_bite's contract: `bad` must be 1 (the detector fired on the crafted bad input) and `good`
386 // must be 0 (it stayed silent on the crafted good one). Both are counts of the SAME event -- did
387 // a FAIL marker reach stderr -- so neither can be satisfied by an always-on or always-off channel.
388 var bad_shouts: i64 = 0
389 var good_shouts: i64 = 0
390
391 let saved_err: i64 = sys_dup3(HPG_FD_STDERR, HPG_FD_ERRSAVE, 0)
392 let ec1: i64 = sys_openat_wr(errcap, HP_MODE_0644)
393 if ec1 >= 0 {
394 sys_dup3(ec1, HPG_FD_STDERR, 0)
395 let p5: i64 = hpg_respond_once(l_ok, r200, n200)
396 hp_run(HPG_PORT_OK, "/api/cap/status" as *u8, need_false, HPG_BUDGET_SEC, badstamp, HPG_TRACE_OFF)
397 hpg_reap(p5)
398 sys_close(ec1)
399 }
400 let ec2: i64 = sys_openat_wr(errcap2, HP_MODE_0644)
401 if ec2 >= 0 {
402 sys_dup3(ec2, HPG_FD_STDERR, 0)
403 sys_unlinkat(stamp)
404 let p6: i64 = hpg_respond_once(l_ok, r200, n200)
405 hp_run(HPG_PORT_OK, "/api/cap/status" as *u8, need_true, HPG_BUDGET_SEC, stamp, HPG_TRACE_OFF)
406 hpg_reap(p6)
407 sys_close(ec2)
408 }
409 if saved_err >= 0 { sys_dup3(HPG_FD_ERRSAVE, HPG_FD_STDERR, 0) }
410
411 let eb: *u8 = sys_mmap(HPG_BUF)
412 let en1: i64 = hpg_slurp(errcap, eb, HPG_BUF)
413 if en1 > 0 { if hp_contains(eb, en1, "verdict=FAIL reason=pattern-absent" as *u8) == 1 { bad_shouts = 1 } }
414 let en2: i64 = hpg_slurp(errcap2, eb, HPG_BUF)
415 if en2 > 0 { if hp_contains(eb, en2, "verdict=FAIL" as *u8) == 1 { good_shouts = 1 } }
416 gv_puts(" stderr bytes on the failing run=" as *u8); gv_num(en1)
417 gv_puts(" on the clean run=" as *u8); gv_num(en2); gv_puts("\n" as *u8)
418 gv_bite("a-failing-run-NAMES-its-reason-on-stderr-which-survives-stdout-to-dev-null" as *u8, bad_shouts, good_shouts, ctr)
419
420 sys_close(l_ok)
421 sys_close(l_500)
422 sys_close(l_hang)
423 sys_unlinkat(stamp)
424
425 let rc: i64 = gv_verdict("HTTP-PROBE-GATE" as *u8, ctr, "each tooth name carries its own strength; read the vector, not this line" as *u8)
426 sys_exit(rc)
427 return rc
428}