code wiki / _hdl_build / nx_init_live.nx
nx_init_live.nx source
↩ module page · 143 lines · 8744 B
1// nx_init_live.nx -- GATE: REAL process supervision. Reworks nx_init (dependency-ordered start, Kahn topo) +
2// nx_supervise (restart-with-give-up-cap) onto ACTUAL forked child processes with wait4(WNOHANG) liveness -- closing
3// the INIT-SERVICES census gap ("real fork/wait liveness wiring"). Grounded on the banked field research (pp_init/
4// pp_wait/pp_zombie/pp_systemd/pp_runit): PID1 reaps children; a supervisor detects death via wait4 and restarts with
5// backoff + a give-up cap (no restart storm). The liveness primitive is proven (nx_initlive_probe: real fork + wait4
6// WNOHANG detects death w/ exit code, distinguishes alive).
7// Services (dependency-ordered): base(healthy) <- worker(crashy, the cap demo) & logger(healthy).
8// T1 dependency-ordered start (topo): base starts before its dependents; order respected.
9// T2 healthy services (base+logger) stay ALIVE with 0 restarts -- wait4 WNOHANG reported alive every tick (REAL).
10// T3 the crashy worker is DETECTED dead + re-forked until the cap -> gaveup (real death-detection + restart loop).
11// T4 teeth: the worker's (cap+1) spawns are ALL DISTINCT pids (genuine new processes) + restarts NEVER exceed cap.
12// T5 teardown: the healthy children are blocking-reaped (real pids, no zombie left).
13// expect_exit: 0 Sovereign: nx_syscalls (fork/wait4/poll). NEVER-BRICK: forks+reaps userspace procs, 0 firmware.
14import "nx_syscalls.nx"
15const ST_MAGIC_1500: i64 = 1500
16
17func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
18func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 }
19func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c }
20func sleep_ms(ms: i64) -> i64 { sys_poll(0 as *u8, 0, ms); return 0 }
21
22const MAXD: i64 = 4
23const ST_RUNNING: i64 = 1
24const ST_GAVEUP: i64 = 2
25const K_HEALTHY: i64 = 0
26const K_CRASHY: i64 = 1
27
28// --- dependency-ordered start (Kahn topo) -- the nx_init algorithm, inlined ---
29func nx_topo(ndep: *i64, dep: *i64, N: i64, order: *i64) -> i64 {
30 let indeg: *i64 = sys_mmap(N*8) as *i64; let done: *i64 = sys_mmap(N*8) as *i64
31 var i: i64=0; while i<N { indeg[i]=ndep[i]; done[i]=0; i=i+1 }
32 var oc: i64=0; var changed: i64=1
33 while changed==1 {
34 changed=0; var u: i64=0
35 while u<N {
36 if done[u]==0 { if indeg[u]==0 {
37 order[oc]=u; oc=oc+1; done[u]=1; changed=1
38 var v: i64=0
39 while v<N { if done[v]==0 { var k: i64=0; while k<ndep[v] { if dep[v*MAXD+k]==u { indeg[v]=indeg[v]-1 } k=k+1 } } v=v+1 }
40 } }
41 u=u+1
42 }
43 }
44 return oc
45}
46func nx_order_ok(order: *i64, oc: i64, ndep: *i64, dep: *i64, N: i64) -> i64 {
47 if oc != N { return 0 }
48 let pos: *i64 = sys_mmap(N*8) as *i64
49 var i: i64=0; while i<oc { pos[order[i]]=i; i=i+1 }
50 var u: i64=0
51 while u<N { var k: i64=0; while k<ndep[u] { if pos[dep[u*MAXD+k]] >= pos[u] { return 0 } k=k+1 } u=u+1 }
52 return 1
53}
54
55// spawn service i as a REAL child: healthy sleeps past the window then exits 0; crashy exits immediately.
56func spawn(kind: *i64, pid: *i64, i: i64) -> i64 {
57 let p: i64 = sys_fork()
58 if p == 0 {
59 if kind[i] == K_HEALTHY { sleep_ms(ST_MAGIC_1500) }
60 sys_exit(0); return 0
61 }
62 pid[i] = p
63 return p
64}
65
66func main() -> i64 {
67 g_puts("nx_init_live (REAL process supervision: fork children + wait4 WNOHANG liveness + restart-with-cap, dependency-ordered)\n" as *u8)
68 var pass: i64=0; var total: i64=0
69 let N: i64=3; let cap: i64=5; let TICKS: i64=60
70 // graph: 0 base (no deps) | 1 worker <- base | 2 logger <- base
71 let ndep: *i64=sys_mmap(N*8) as *i64; let dep: *i64=sys_mmap(N*MAXD*8) as *i64; let nm: *i64=sys_mmap(N*8) as *i64
72 let kind: *i64=sys_mmap(N*8) as *i64
73 nm[0]=("base" as *u8) as i64; nm[1]=("worker" as *u8) as i64; nm[2]=("logger" as *u8) as i64
74 kind[0]=K_HEALTHY; kind[1]=K_CRASHY; kind[2]=K_HEALTHY
75 ndep[0]=0
76 ndep[1]=1; dep[1*MAXD+0]=0
77 ndep[2]=1; dep[2*MAXD+0]=0
78
79 let order: *i64=sys_mmap(N*8) as *i64
80 let oc: i64=nx_topo(ndep, dep, N, order)
81 let ordok: i64=nx_order_ok(order, oc, ndep, dep, N)
82 g_puts(" start order: "); var oi: i64=0; while oi<oc { g_puts(nm[order[oi]] as *u8); if oi<oc-1 { g_puts(" -> " as *u8) } oi=oi+1 } g_puts("\n" as *u8)
83 var t1: i64=0; if oc==N { if ordok==1 { if order[0]==0 { t1=1 } } }
84 pass=pass+ck("T1: dependency-ordered start -- base before its dependents (topo, order respected)" as *u8, t1); total=total+1
85
86 // supervise state
87 let pid: *i64=sys_mmap(N*8) as *i64; let state: *i64=sys_mmap(N*8) as *i64; let restarts: *i64=sys_mmap(N*8) as *i64
88 let st: *i64=sys_mmap(16) as *i64
89 // worker pid history (initial + up to cap restarts) to prove genuine new processes
90 let phist: *i64=sys_mmap((cap+2)*8) as *i64; var ph: i64=0
91
92 // initial spawn IN TOPO ORDER
93 var s: i64=0; while s<N { let i: i64=order[s]; state[i]=ST_RUNNING; restarts[i]=0; spawn(kind,pid,i); if i==1 { phist[ph]=pid[1]; ph=ph+1 } s=s+1 }
94
95 // supervision loop: detect death (wait4 WNOHANG) -> restart until cap -> gaveup
96 var tick: i64=0
97 while tick<TICKS {
98 var j: i64=0
99 while j<N {
100 if state[j]==ST_RUNNING {
101 st[0]=0
102 let r: i64=sys_wait4(pid[j], st, WNOHANG)
103 if r==pid[j] {
104 if restarts[j]<cap { restarts[j]=restarts[j]+1; spawn(kind,pid,j); if j==1 { phist[ph]=pid[1]; ph=ph+1 } }
105 else { state[j]=ST_GAVEUP }
106 }
107 }
108 j=j+1
109 }
110 sleep_ms(25); tick=tick+1
111 }
112
113 g_puts(" after "); g_pn(TICKS); g_puts(" ticks: base(restarts="); g_pn(restarts[0]); g_puts(",state="); g_pn(state[0]); g_puts(") worker(restarts="); g_pn(restarts[1]); g_puts(",state="); g_pn(state[1]); g_puts(",spawns="); g_pn(ph); g_puts(") logger(restarts="); g_pn(restarts[2]); g_puts(",state="); g_pn(state[2]); g_puts(")\n" as *u8)
114
115 var t2: i64=0; if restarts[0]==0 { if state[0]==ST_RUNNING { if restarts[2]==0 { if state[2]==ST_RUNNING { t2=1 } } } }
116 pass=pass+ck("T2: healthy services (base+logger) stay ALIVE with 0 restarts -- wait4 reported alive every tick" as *u8, t2); total=total+1
117
118 var t3: i64=0; if restarts[1]==cap { if state[1]==ST_GAVEUP { t3=1 } }
119 pass=pass+ck("T3: the crashy worker is detected dead + re-forked to the cap -> GAVEUP (real death-detect + restart loop)" as *u8, t3); total=total+1
120
121 // T4 teeth: all worker spawns distinct + restarts never exceed cap
122 var distinct: i64=1; var a: i64=0
123 while a<ph { var b: i64=a+1; while b<ph { if phist[a]==phist[b] { distinct=0 } b=b+1 } a=a+1 }
124 var t4: i64=0; if distinct==1 { if ph==cap+1 { if restarts[1]<=cap { t4=1 } } }
125 g_puts(" worker pids: "); var pp: i64=0; while pp<ph { g_pn(phist[pp]); if pp<ph-1 { g_puts(" " as *u8) } pp=pp+1 } g_puts(" (all distinct="); g_pn(distinct); g_puts(")\n" as *u8)
126 pass=pass+ck("T4 (teeth): the worker's cap+1 spawns are ALL DISTINCT pids (genuine processes) + restarts never exceed cap" as *u8, t4); total=total+1
127
128 // T5 teardown: blocking-reap the healthy children (no zombies) -- returns their real pids
129 let rb0: i64=sys_wait4(pid[0], st, 0)
130 let rb2: i64=sys_wait4(pid[2], st, 0)
131 var t5: i64=0; if rb0==pid[0] { if rb2==pid[2] { t5=1 } }
132 g_puts(" teardown blocking-reap: base="); g_pn(rb0); g_puts(" logger="); g_pn(rb2); g_puts(" (real pids reaped, no zombie)\n" as *u8)
133 pass=pass+ck("T5: the healthy children are blocking-reaped cleanly (real pids, no zombie left)" as *u8, t5); total=total+1
134
135 var okall: i64=0; if pass==total { okall=1 }
136 g_puts("---- nx_init_live: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8)
137 if okall==1 {
138 let logf: i64=sys_openat_append("knowledge/status/init_live.log" as *u8, 420)
139 if logf>=0 { let z: i64=sys_write(logf,"NXINITLIVE GREEN: REAL process supervision -- fork children + wait4 WNOHANG liveness + restart-with-cap (distinct pids) + dependency-ordered start; healthy alive, crashy gaveup at cap\n" as *u8,175); sys_close(logf) }
140 g_puts("verdict=GREEN (REAL fork/wait4 process supervision: dependency-ordered start, live death-detection, bounded restart -- the INIT-SERVICES real-liveness gap closed)\n" as *u8); sys_exit(0); return 0
141 }
142 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
143}