code wiki / (root) / nx_health_probe_gate.nx

nx_health_probe_gate.nx source

↩ module page · 83 lines · 4786 B

1// nx_health_probe_gate.nx -- loopback KAT for the serving health probe. Forks two mock servers (one that 2// serves 200, one that ACCEPTS but never responds = hung) + probes an unused port. Proves the probe tells 3// SERVING / HUNG / REFUSED apart -- crucially HUNG, which PID-liveness + a LISTEN check both miss. 4// exit 0 = pass, N = assertion N failed. 5import "nx_health_probe.nx" 6import "nx_assert.nx" 7 8// sized: throwaway loopback ports in the same block as the existing mocks 9const HPG_PORT_BOUND: i64 = 19004 10const HPG_PORT_DEAD: i64 = 19005 11// derived: must outlast two confirm gaps (2 x HP_CONFIRM_GAP_MS) plus connect timeouts, with margin 12const HPG_HOLD_MS: i64 = 4000 13 14// bind+listen `port`, fork a one-shot handler. mode 0 = reply 200, mode 1 = accept then HANG (no reply). 15// mode 2 = bind, then CLOSE the listen socket and stay ALIVE = THE seq1299 WOUND REPRODUCED (the state 16// every liveness-only guard reads as healthy). mode 3 = stay BOUND but never accept = a merely BUSY 17// daemon, which the probe must NOT accuse (the redirect.elf false-positive class). 18func hpg_mock(port: i64, mode: i64) -> i64 { 19 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0); if lfd < 0 { return 0 - 1 } 20 let opt: *u8 = sys_mmap(4); opt[0]=1 as u8; sys_setsockopt(lfd, 1, 2, opt, 4) // SO_REUSEADDR 21 let addr: *u8 = sys_mmap(16); hp_sockaddr(addr, port, 0, 0, 0, 0) // bind 0.0.0.0:port 22 if sys_bind(lfd, addr, 16) != 0 { sys_close(lfd); return 0 - 1 } 23 sys_listen(lfd, 8) 24 let pid: i64 = sys_fork() 25 if pid == 0 { 26 if mode == 2 { sys_close(lfd); sys_sleep_ms(HPG_HOLD_MS); sys_exit(0) } 27 if mode == 3 { sys_sleep_ms(HPG_HOLD_MS); sys_close(lfd); sys_exit(0) } 28 let cfd: i64 = sys_accept(lfd) 29 if cfd >= 0 { 30 let rb: *u8 = sys_mmap(4096); sys_read(cfd, rb, 4095) 31 if mode == 0 { 32 let resp: *u8 = "HTTP/1.1 200 OK\r\nContent-Length: 2\r\nConnection: close\r\n\r\nok" as *u8 33 var rl: i64 = 0; while resp[rl] != (0 as u8) { rl = rl + 1 } 34 sys_write(cfd, resp, rl) 35 } else { sys_sleep_ms(5000) } // HANG: never reply within the probe's 3s timeout 36 sys_close(cfd) 37 } 38 sys_close(lfd); sys_exit(0) 39 } 40 sys_close(lfd) 41 return pid 42} 43 44func main() -> i64 { 45 let p1: i64 = hpg_mock(19001, 0) // serving mock 46 let p2: i64 = hpg_mock(19002, 1) // hung mock 47 sys_sleep_ms(150) // let the children reach accept() 48 49 let v1: i64 = hp_probe(19001, 3) 50 nx_puts_err("SERVING mock -> "); nx_puts_err(hp_name(v1)); nx_puts_err("\n" as *u8) 51 let v2: i64 = hp_probe(19002, 3) // ~3s: connect ok, recv times out -> HUNG 52 nx_puts_err("HUNG mock -> "); nx_puts_err(hp_name(v2)); nx_puts_err("\n" as *u8) 53 let v3: i64 = hp_probe(19003, 3) // nothing bound -> connect refused 54 nx_puts_err("no-daemon -> "); nx_puts_err(hp_name(v3)); nx_puts_err("\n" as *u8) 55 56 let st: *i64 = sys_mmap(16) as *i64 57 nx_kill(p1, 9); sys_wait4(p1, st, 0); nx_kill(p2, 9); sys_wait4(p2, st, 0) 58 59 if v1 != HP_SERVING { return 1 } 60 if v2 != HP_HUNG { return 2 } // ★ the exceed: a hung daemon is CAUGHT 61 if v3 != HP_REFUSED { return 3 } 62 63 // ---- seq1299: CONNECT-ONLY readiness (the state that took the MCP surface dark) ---- 64 let p4: i64 = hpg_mock(HPG_PORT_BOUND, 3) // ALIVE + BOUND, never accepts (a merely BUSY daemon) 65 let p5: i64 = hpg_mock(HPG_PORT_DEAD, 2) // ALIVE + socket CLOSED (THE WOUND) 66 sys_sleep_ms(150) 67 let l4: i64 = hp_listening(HPG_PORT_BOUND) 68 let d4: i64 = hp_socket_dead(HPG_PORT_BOUND) 69 let d5: i64 = hp_socket_dead(HPG_PORT_DEAD) 70 nx_puts_err("bound+busy -> listening="); nx_puti_err(l4); nx_puts_err(" socket_dead="); nx_puti_err(d4); nx_puts_err("\n" as *u8) 71 nx_puts_err("alive+closed -> socket_dead="); nx_puti_err(d5); nx_puts_err("\n" as *u8) 72 nx_kill(p4, 9); sys_wait4(p4, st, 0); nx_kill(p5, 9); sys_wait4(p5, st, 0) 73 74 if l4 != 1 { return 4 } // a BOUND socket must read as listening even when nothing ever accepts 75 if d4 != 0 { return 5 } // ANTI-FALSE-POSITIVE: never accuse a busy-but-bound daemon (redirect.elf class) 76 if d5 != 1 { return 6 } // ★THE WOUND: process ALIVE, listen socket GONE -> CONFIRMED dead 77 78 nx_puts_err("--- vs systemd PID-liveness / nx_hostctl /proc-name-scan ---\n" as *u8) 79 nx_puts_err("HUNG (process up + port bound but not responding): systemd/proc-scan = ALIVE (MISS) ; nishi = HUNG (CAUGHT) -> EXCEEDS\n" as *u8) 80 nx_puts_err("ALIVE + listen socket GONE: PID-liveness = HEALTHY (MISS, the 2026-07-29 MCP outage) ; nishi = CONFIRMED-DEAD (CAUGHT) -> EXCEEDS\n" as *u8) 81 nx_puts_err("nx_health_probe_gate verdict=GREEN pass=6\n" as *u8) 82 return 0 83}