nx_survey_handoff_gate.nx source
↩ module page · 460 lines · 20964 B
1// nx_survey_handoff_gate.nx -- TS1 ADOPTION: THE REAL DAEMON, RESTARTED FOR REAL, ZERO DROPS.
2//
3// /compare/trafficsafety rung TS1. nx_ts_handoff_gate already proved the MECHANISM on a synthetic
4// server. This gate proves the ADOPTION, which is the half that was open: it fork+execs the ACTUAL
5// nx_survey_daemon binary, restarts it for real, and measures what a client saw. Nothing here checks
6// that the source references a symbol -- a reference is not an adoption, and the estate has a long
7// record of capabilities that were referenced and never reached.
8//
9// ACCEPT RULE, taken VERBATIM from trafficsafety.plan and not re-invented here: "a swap under a
10// synthetic request stream drops ZERO connections, measured by a client that counts refusals and
11// resets, not by the daemon's own log. The neg-control is mandatory -- the same harness against the
12// CURRENT ordinary-listener path must show a non-zero drop, or the test proves nothing."
13//
14// THE TWO ARMS DIFFER IN EXACTLY ONE THING: whether an owner outside the daemon is publishing the
15// listening socket. Same binary, same argv shape, same client, same request count. In the ARMED arm
16// an owner holds the listener and hands it to each generation, so ts_handoff_nodrop INHERITS it; in
17// the NEG-CONTROL there is no owner, so the very same call falls back to binding -- which is today's
18// behaviour for every other daemon in the estate, and is the disease state.
19//
20// THE DECISIVE MOMENT IS THE ARRIVAL DURING THE GAP. Generation one is killed AND REAPED, so at that
21// instant ZERO daemon processes exist. A client connects right then. With an owner the handshake
22// completes into the kernel's accept queue and generation two serves it; without one there is nothing
23// bound and the arrival is refused with ECONNREFUSED. That difference is deterministic, which is what
24// makes this a gate and not a flaky benchmark.
25//
26// IT ALSO EXERCISES ENVOY'S ORDERING RULE, WHICH IS WHY THE PUBLISH IS THE READINESS SIGNAL.
27// ts_handoff_publish blocks until a generation asks for the socket, and the adopted daemon asks only
28// AFTER it has finished every expensive step (its three arenas and the seg-store warm). So a publish
29// that returns is positive evidence that initialisation completed BEFORE the handoff -- the exact
30// ordering whose absence caused this estate's 8-minute blackout.
31//
32// SAFETY: loopback only; every port is FOUND by a bind that would have failed had it been occupied,
33// because a probe port you did not verify free is not a control, it is a second instance. The live
34// :8031 survey daemon is NEVER touched -- the subject is given its own port on argv precisely so this
35// gate can drive a real restart without becoming a second instance of a running service. The subject
36// runs with CWD inside the gate's own /tmp fixture, so its store self-heal cannot write into a
37// production tree.
38// expect_exit: 0 license_tier: ORIGINAL No hw writes (Rule 26).
39import "nx_syscalls.nx"
40import "nx_http_server.nx"
41import "nx_gate_emit_lib.nx"
42import "nx_gate_verdict.nx"
43
44const SH_NUM_SCRATCH: i64 = 24
45const SH_ASCII_ZERO: i64 = 48
46const SH_B10: i64 = 10
47const SH_ONE: i64 = 1
48const SH_SA_BYTES: i64 = 16
49// sockaddr_in FIELD OFFSETS, named so a reader checks them against the platform layout instead of
50// meeting bare indices: sin_family at 0, sin_port at 2 (big-endian), sin_addr at 4.
51const SH_SA_PORT_OFF: i64 = 2
52const SH_SA_ADDR_OFF: i64 = 4
53const SH_ADDR_BYTES: i64 = 4
54const SH_BYTE_RADIX: i64 = 256
55const SH_OUT_SLOTS: i64 = 12
56const SH_OUT_BYTES: i64 = 128
57const SH_LOOPBACK_A: i64 = 127
58const SH_LOOPBACK_D: i64 = 1
59const SH_PORT_BASE: i64 = 39500
60const SH_PORT_TRIES: i64 = 64
61const SH_PORT_NONE: i64 = 0 - 1
62const SH_TRUE: i64 = 1
63const SH_FALSE: i64 = 0
64const SH_PATHBUF: i64 = 256
65const SH_ARGV_BYTES: i64 = 64
66const SH_RESP_CAP: i64 = 4096
67const SH_SIG_TERM: i64 = 15
68// Exit code a child uses when execve itself failed -- an absent artifact must NAME itself rather
69// than surface to the caller as a dead server. 127 is the shell's own convention for not-found.
70const SH_RC_EXEC_FAILED: i64 = 127
71const SH_ARGC_SUBJECT: i64 = 2
72// argv slots of the spawned daemon, named rather than left as bare indices at the call site.
73const SH_AV_PORT: i64 = 1
74const SH_AV_SOCK: i64 = 2
75const SH_AV_END: i64 = 3
76// Both generations of the swap -- the denominator the neg-control's attribution tooth asserts against.
77const SH_BOTH_GENERATIONS: i64 = 2
78
79// The request stream per generation is taken from the rendezvous backlog rather than picked: it
80// exercises the accept queue at the queue's own scale on both sides of the swap. The decisive tooth
81// does not depend on it -- the in-gap arrival is a single deterministic event -- so this number only
82// sets how much "the daemon was really serving" evidence surrounds that event.
83const SH_REQS_PER_GEN: i64 = TS_RV_BACKLOG
84// Bounds exist only so a broken run fails LOUD instead of hanging. Reusing the shim's established
85// socket deadline rather than inventing a second budget for the same kind of wait.
86const SH_DEADLINE_S: i64 = ACCEPT_TMO_S
87// Readiness poll granularity for the NEG-CONTROL arm only. The armed arm needs none -- its publish IS
88// the readiness signal -- but a self-binding daemon offers no such edge, so the harness must retry the
89// connect until the bind lands. This is a harness poll interval, not a product threshold, and the
90// TOTAL wait it participates in is bounded by SH_DEADLINE_S above.
91const SH_READY_POLL_MS: i64 = 20
92const SH_READY_TRIES: i64 = (SH_DEADLINE_S * 1000) / SH_READY_POLL_MS
93
94const SH_O_ATTEMPTED: i64 = 0
95const SH_O_SERVED: i64 = 1
96const SH_O_GAP_RC: i64 = 2
97const SH_O_GAP_DONE: i64 = 3
98const SH_O_PORT: i64 = 4
99const SH_O_G1READY: i64 = 5
100const SH_O_G2READY: i64 = 6
101
102const SH_DIR: *u8 = "/tmp/nx_survey_handoff_gate" as *u8
103const SH_SOCK_ARMED: *u8 = "/tmp/nx_survey_handoff_gate/armed.sock" as *u8
104const SH_SOCK_NEG: *u8 = "/tmp/nx_survey_handoff_gate/neg.sock" as *u8
105const SH_DEFAULT_DAEMON: *u8 = "./nx_survey_daemon.elf" as *u8
106const SH_REQ: *u8 = "GET /survey HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n" as *u8
107
108func g_putn(v: i64) -> i64 {
109 if v == 0 { sys_write(1, "0" as *u8, 1); return 0 }
110 var m: i64 = v
111 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
112 let d: *u8 = sys_mmap(SH_NUM_SCRATCH); var k: i64 = 0
113 while m > 0 { d[k] = ((SH_ASCII_ZERO + (m - (m / SH_B10) * SH_B10)) as u8); m = m / SH_B10; k = k + 1 }
114 var j: i64 = k - 1
115 while j >= 0 { sys_write(1, ((d as i64)+j) as *u8, 1); j = j - 1 }
116 return 0
117}
118
119func gq(label: *u8, got: i64, want: i64, ctr: *i64) -> i64 {
120 var c: i64 = 0
121 if got == want { c = 1 }
122 let r: i64 = gv_check(label, c, ctr)
123 if c == 0 {
124 g_puts(" got=" as *u8); g_putn(got)
125 g_puts(" want=" as *u8); g_putn(want)
126 g_puts("\n" as *u8)
127 }
128 return r
129}
130
131func sh_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
132
133func sh_itoa(v: i64, out: *u8) -> i64 {
134 if v == 0 { out[0] = SH_ASCII_ZERO as u8; out[1] = 0 as u8; return 1 }
135 var m: i64 = v
136 let t: *u8 = sys_mmap(SH_NUM_SCRATCH)
137 var k: i64 = 0
138 while m > 0 { t[k] = ((SH_ASCII_ZERO + (m - (m / SH_B10) * SH_B10)) as u8); m = m / SH_B10; k = k + 1 }
139 var j: i64 = 0
140 while j < k { out[j] = t[k - 1 - j]; j = j + 1 }
141 out[k] = 0 as u8
142 return k
143}
144
145func sh_sa(sa: *u8, port: i64) -> i64 {
146 var i: i64 = 0
147 while i < SH_SA_BYTES { sa[i] = 0; i = i + 1 }
148 // The zero-fill above already cleared every other octet, so only the non-zero lanes are written.
149 sa[0] = AF_INET
150 sa[SH_SA_PORT_OFF] = port / SH_BYTE_RADIX
151 sa[SH_SA_PORT_OFF + 1] = port % SH_BYTE_RADIX
152 sa[SH_SA_ADDR_OFF] = SH_LOOPBACK_A
153 sa[SH_SA_ADDR_OFF + SH_ADDR_BYTES - 1] = SH_LOOPBACK_D
154 return 0
155}
156
157// reuse=0 makes the bind ITSELF the free-port check.
158func sh_listen(port: i64, reuse: i64) -> i64 {
159 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
160 if fd < 0 { return fd }
161 if reuse == SH_TRUE {
162 let ra: *u8 = sys_mmap(SCM_U32_BYTES)
163 var z: i64 = 0
164 while z < SCM_U32_BYTES { ra[z] = 0 as u8; z = z + 1 }
165 ra[0] = 1
166 sys_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, ra, SCM_U32_BYTES)
167 }
168 let sa: *u8 = sys_mmap(SH_SA_BYTES)
169 sh_sa(sa, port)
170 if sys_bind(fd, sa, SH_SA_BYTES) < 0 { sys_close(fd); return 0 - 1 }
171 if sys_listen(fd, TS_RV_BACKLOG) < 0 { sys_close(fd); return 0 - 1 }
172 return fd
173}
174
175func sh_find_port(from: i64) -> i64 {
176 var t: i64 = 0
177 while t < SH_PORT_TRIES {
178 let cand: i64 = from + t
179 let fd: i64 = sh_listen(cand, SH_FALSE)
180 if fd >= 0 { sys_close(fd); return cand }
181 t = t + 1
182 }
183 return SH_PORT_NONE
184}
185
186func sh_connect(port: i64) -> i64 {
187 let sa: *u8 = sys_mmap(SH_SA_BYTES)
188 sh_sa(sa, port)
189 let fd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
190 if fd < 0 { return 0 - 1 }
191 sys_set_socket_timeout(fd, SH_DEADLINE_S)
192 if sys_connect(fd, sa, SH_SA_BYTES) < 0 { sys_close(fd); return 0 - 1 }
193 return fd
194}
195
196// Complete one REAL HTTP exchange on an already-connected socket. 1 = served, 0 = dropped.
197// ANY HTTP response counts as served: this gate measures whether the CONNECTION survived the swap,
198// not whether the application liked the path -- conflating the two would let an app-level 404 read
199// as a dropped connection and would make the number mean nothing.
200func sh_exchange(fd: i64) -> i64 {
201 let n: i64 = sh_slen(SH_REQ)
202 if sys_write(fd, SH_REQ, n) != n { return 0 }
203 let b: *u8 = sys_mmap(SH_RESP_CAP)
204 let r: i64 = sys_read(fd, b, SH_RESP_CAP)
205 // BIND THE LITERAL ONCE AND DERIVE ITS LENGTH. This was four character codes -- 72,84,84,80 --
206 // which is the string "HTTP" written so no reader recognises it and no grep finds it, with a
207 // hand-counted 4 beside it that would drift the moment the marker changed.
208 let want: *u8 = "HTTP" as *u8
209 var wl: i64 = 0
210 while want[wl] != (0 as u8) { wl = wl + 1 }
211 if r < wl { return 0 }
212 var q: i64 = 0
213 while q < wl { if b[q] != want[q] { return 0 } q = q + 1 }
214 return 1
215}
216
217func sh_drive_one(port: i64) -> i64 {
218 let fd: i64 = sh_connect(port)
219 if fd < 0 { return 0 }
220 let ok: i64 = sh_exchange(fd)
221 sys_close(fd)
222 return ok
223}
224
225// START ONE GENERATION OF THE REAL DAEMON. CWD is moved into the gate's fixture first so the
226// subject's store self-heal cannot write into a production tree.
227func sh_spawn(daemon: *u8, port: i64, sockp: *u8) -> i64 {
228 let pb: *u8 = sys_mmap(SH_NUM_SCRATCH)
229 sh_itoa(port, pb)
230 let pid: i64 = sys_fork()
231 if pid != 0 { return pid }
232 sys_chdir(SH_DIR)
233 let av: *i64 = (sys_mmap(SH_ARGV_BYTES)) as *i64
234 av[0] = daemon as i64
235 av[SH_AV_PORT] = pb as i64
236 av[SH_AV_SOCK] = sockp as i64
237 av[SH_AV_END] = 0
238 let ev: *i64 = (sys_mmap(SH_ARGV_BYTES)) as *i64
239 ev[0] = 0
240 // NOT sys_execve_clean: that closes fds 3..1023, which would destroy an inherited listener.
241 sys_execve(daemon, av, ev)
242 // AN ABSENT ARTIFACT IS INDISTINGUISHABLE FROM A DEAD SERVER unless the exec failure is named.
243 sys_exit(SH_RC_EXEC_FAILED)
244 return 0
245}
246
247func sh_reap(pid: i64) -> i64 {
248 nx_kill(pid, SH_SIG_TERM)
249 let st: *i64 = (sys_mmap(SH_OUT_BYTES)) as *i64
250 st[0] = 0
251 sys_wait4(pid, st, 0)
252 return wait_status_rc(st[0])
253}
254
255// Wait until a self-binding daemon is actually listening. Bounded, and its success is asserted as an
256// anti-vacuity condition rather than assumed.
257func sh_wait_ready(port: i64) -> i64 {
258 var t: i64 = 0
259 while t < SH_READY_TRIES {
260 let fd: i64 = sh_connect(port)
261 if fd >= 0 { sys_close(fd); return 1 }
262 sys_sleep_ms(SH_READY_POLL_MS)
263 t = t + 1
264 }
265 return 0
266}
267
268// THE EXPERIMENT. Identical script for both arms; the ONLY difference is whether an owner outside the
269// daemon publishes the listening socket. Returns dropped connections, or -1 if the harness could not
270// be set up at all -- which is reported as UNOBSERVED, never as a pass.
271func sh_swap_run(armed: i64, daemon: *u8, port: i64, sockp: *u8, out: *i64) -> i64 {
272 var k: i64 = 0
273 while k < SH_OUT_SLOTS { out[k] = 0; k = k + 1 }
274 out[SH_O_PORT] = port
275 sys_unlinkat(sockp)
276 let vb: *i64 = (sys_mmap(SH_OUT_BYTES)) as *i64
277 vb[0] = 0
278 var rv: i64 = 0 - 1
279 var lsock: i64 = 0 - 1
280 if armed == SH_TRUE {
281 rv = ts_handoff_open(sockp, vb)
282 if rv < 0 { return 0 - 1 }
283 sys_set_socket_timeout(rv, SH_DEADLINE_S)
284 // THE OWNER'S COPY IS THE GUARANTEE: it is opened before any generation exists and closed
285 // only after the last one, so there is no instant at which zero processes hold the port.
286 lsock = sh_listen(port, SH_FALSE)
287 if lsock < 0 { sys_close(rv); return 0 - 1 }
288 }
289
290 var drops: i64 = 0
291 var attempted: i64 = 0
292 var served: i64 = 0
293
294 // ---- generation one
295 let g1: i64 = sh_spawn(daemon, port, sockp)
296 if armed == SH_TRUE {
297 // The publish RETURNS only once the daemon asked for the socket, and it asks only after every
298 // expensive init step -- so this returning is the evidence for Envoy's ordering rule.
299 if ts_handoff_publish(rv, lsock, vb) < 0 {
300 sh_reap(g1); sys_close(rv); sys_close(lsock); sys_unlinkat(sockp); return 0 - 1
301 }
302 out[SH_O_G1READY] = 1
303 } else {
304 out[SH_O_G1READY] = sh_wait_ready(port)
305 if out[SH_O_G1READY] == 0 { sh_reap(g1); return 0 - 1 }
306 }
307 var i: i64 = 0
308 while i < SH_REQS_PER_GEN {
309 attempted = attempted + 1
310 let ok: i64 = sh_drive_one(port)
311 if ok == 1 { served = served + 1 } else { drops = drops + 1 }
312 i = i + 1
313 }
314
315 // ---- THE GAP. Generation one is killed AND REAPED: at this instant ZERO daemon processes exist.
316 sh_reap(g1)
317 let sa: *u8 = sys_mmap(SH_SA_BYTES)
318 sh_sa(sa, port)
319 let gap: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
320 sys_set_socket_timeout(gap, SH_DEADLINE_S)
321 let grc: i64 = sys_connect(gap, sa, SH_SA_BYTES)
322 out[SH_O_GAP_RC] = grc
323 out[SH_O_GAP_DONE] = 1
324 attempted = attempted + 1
325 if grc < 0 { drops = drops + 1 }
326
327 // ---- generation two, which must also serve the in-gap arrival when it survived.
328 let g2: i64 = sh_spawn(daemon, port, sockp)
329 if armed == SH_TRUE {
330 if ts_handoff_publish(rv, lsock, vb) >= 0 { out[SH_O_G2READY] = 1 }
331 } else {
332 out[SH_O_G2READY] = sh_wait_ready(port)
333 }
334 if grc == 0 {
335 if out[SH_O_G2READY] == 1 {
336 if sh_exchange(gap) == 1 { served = served + 1 } else { drops = drops + 1 }
337 } else { drops = drops + 1 }
338 }
339 sys_close(gap)
340 if out[SH_O_G2READY] == 1 {
341 var j: i64 = 0
342 while j < SH_REQS_PER_GEN {
343 attempted = attempted + 1
344 let ok2: i64 = sh_drive_one(port)
345 if ok2 == 1 { served = served + 1 } else { drops = drops + 1 }
346 j = j + 1
347 }
348 }
349 sh_reap(g2)
350 if lsock >= 0 { sys_close(lsock) }
351 if rv >= 0 { sys_close(rv) }
352 sys_unlinkat(sockp)
353 out[SH_O_ATTEMPTED] = attempted
354 out[SH_O_SERVED] = served
355 return drops
356}
357
358func sh_report(tag: *u8, drops: i64, out: *i64) -> i64 {
359 g_puts(" " as *u8); g_puts(tag)
360 g_puts(" port=" as *u8); g_putn(out[SH_O_PORT])
361 g_puts(" attempted=" as *u8); g_putn(out[SH_O_ATTEMPTED])
362 g_puts(" served=" as *u8); g_putn(out[SH_O_SERVED])
363 g_puts(" drops=" as *u8); g_putn(drops)
364 g_puts(" in_gap_connect_rc=" as *u8); g_putn(out[SH_O_GAP_RC])
365 g_puts(" gen1_ready=" as *u8); g_putn(out[SH_O_G1READY])
366 g_puts(" gen2_ready=" as *u8); g_putn(out[SH_O_G2READY])
367 g_puts("\n" as *u8)
368 return 0
369}
370
371func main(argc: i64, argv: **u8) -> i64 {
372 let ctr: *i64 = gv_ctr()
373 gv_head("nx_survey_handoff_gate -- TS1 ADOPTION: the REAL daemon restarted, measured in drops" as *u8)
374
375 var daemon: *u8 = SH_DEFAULT_DAEMON
376 if argc >= SH_ARGC_SUBJECT { daemon = argv[1] as *u8 }
377 g_puts(" subject=" as *u8); g_puts(daemon); g_puts("\n" as *u8)
378
379 sys_mkdir(SH_DIR, MODE_0755)
380 sys_unlinkat(SH_SOCK_ARMED)
381 sys_unlinkat(SH_SOCK_NEG)
382
383 // THE SUBJECT MUST EXIST. An absent artifact is indistinguishable from a dead server, so this is
384 // established before anything is measured rather than being read out of a confusing failure.
385 let dl: *i64 = (sys_mmap(SH_OUT_BYTES)) as *i64
386 dl[0] = 0
387 let probe: *u8 = sys_read_file(daemon, dl)
388 var have: i64 = 0
389 if probe != (0 as *u8) { if dl[0] > 0 { have = 1 } }
390 g_puts(" subject_bytes=" as *u8); g_putn(dl[0]); g_puts("\n" as *u8)
391 if gv_need("the subject binary exists and is readable" as *u8, have, ctr) == 0 {
392 let rcs: i64 = gv_verdict("SURVEY-HANDOFF-GATE" as *u8, ctr, "each tooth states its own strength above" as *u8)
393 sys_exit(rcs)
394 return rcs
395 }
396
397 let pa: i64 = sh_find_port(SH_PORT_BASE)
398 var pn: i64 = SH_PORT_NONE
399 if pa != SH_PORT_NONE { pn = sh_find_port(pa + 1) }
400 var ports_ok: i64 = 0
401 if pa != SH_PORT_NONE { if pn != SH_PORT_NONE { if pa != pn { ports_ok = 1 } } }
402 if gv_need("two DISTINCT loopback ports proven free by a bind without SO_REUSEADDR" as *u8, ports_ok, ctr) == 0 {
403 let rcs: i64 = gv_verdict("SURVEY-HANDOFF-GATE" as *u8, ctr, "each tooth states its own strength above" as *u8)
404 sys_exit(rcs)
405 return rcs
406 }
407 gq("T01 the two arms run on DIFFERENT ports so neither can serve the other" as *u8, pa != pn, 1, ctr)
408
409 // ---- ARM 1: ADOPTED. An owner outside the daemon holds the listener.
410 let oa: *i64 = (sys_mmap(SH_OUT_BYTES)) as *i64
411 let da: i64 = sh_swap_run(SH_TRUE, daemon, pa, SH_SOCK_ARMED, oa)
412 sh_report("ADOPTED " as *u8, da, oa)
413 var arm_ran: i64 = 0
414 if da >= 0 { if oa[SH_O_GAP_DONE] == 1 { arm_ran = 1 } }
415 if gv_need("the ADOPTED arm reached the restart with a live request stream" as *u8, arm_ran, ctr) == 1 {
416 // ANTI-VACUITY FIRST: a restart with nothing in flight is UNOBSERVED, never a pass. The
417 // denominator is asserted arithmetically before any verdict about drops is believed.
418 gq("T02 anti-vacuity the ADOPTED arm drove the whole stream across the restart" as *u8,
419 oa[SH_O_ATTEMPTED], SH_REQS_PER_GEN + SH_REQS_PER_GEN + 1, ctr)
420 gq("T03 generation one really served before it was killed and reaped" as *u8, oa[SH_O_G1READY], 1, ctr)
421 gq("T04 ENVOY ORDERING generation two finished its expensive init BEFORE taking the socket" as *u8,
422 oa[SH_O_G2READY], 1, ctr)
423 gq("T05 THE INVARIANT an arrival DURING the restart is not refused" as *u8, oa[SH_O_GAP_RC], 0, ctr)
424 gq("T06 THE ACCEPT RULE zero dropped connections across a REAL restart of the real daemon" as *u8, da, 0, ctr)
425 gq("T07 and every attempted connection was served end to end" as *u8, oa[SH_O_SERVED], oa[SH_O_ATTEMPTED], ctr)
426 }
427
428 // ---- ARM 2: NEG-CONTROL. Same binary, same harness, NO owner -- so ts_handoff_nodrop falls back
429 // to binding, which is what every other daemon in the estate still does. If this does not drop,
430 // the adopted arm's zero proves nothing at all.
431 let on: *i64 = (sys_mmap(SH_OUT_BYTES)) as *i64
432 let dn: i64 = sh_swap_run(SH_FALSE, daemon, pn, SH_SOCK_NEG, on)
433 sh_report("NEG-CTRL" as *u8, dn, on)
434 var neg_ran: i64 = 0
435 if dn >= 0 { if on[SH_O_GAP_DONE] == 1 { neg_ran = 1 } }
436 if gv_need("the NEG-CONTROL arm reached the restart with a live request stream" as *u8, neg_ran, ctr) == 1 {
437 gq("T08 neg-control-same-denominator it drove the same number of connections" as *u8,
438 on[SH_O_ATTEMPTED], oa[SH_O_ATTEMPTED], ctr)
439 var refused: i64 = 0
440 if on[SH_O_GAP_RC] < 0 { refused = 1 }
441 gq("T09 neg-control-bind-per-process the in-gap arrival IS refused" as *u8, refused, 1, ctr)
442 var lost: i64 = 0
443 if dn > 0 { lost = 1 }
444 gq("T10 neg-control-drops the un-adopted path loses connections across a restart" as *u8, lost, 1, ctr)
445 // The control must fail for the RIGHT reason: the port went away, not the harness broke.
446 gq("T11 neg-control-attribution both of its generations really served" as *u8,
447 on[SH_O_G1READY] + on[SH_O_G2READY], SH_BOTH_GENERATIONS, ctr)
448 // Both signals present at once: two arms that each isolate one signal do not prove the
449 // mechanism discriminates between them.
450 var better: i64 = 0
451 if da >= 0 { if dn > da { better = 1 } }
452 gq("T12 the adopted daemon strictly beats its own un-adopted path on the SAME harness" as *u8, better, 1, ctr)
453 }
454
455 sys_unlinkat(SH_SOCK_ARMED)
456 sys_unlinkat(SH_SOCK_NEG)
457 let rc: i64 = gv_verdict("SURVEY-HANDOFF-GATE" as *u8, ctr, "each tooth states its own strength above" as *u8)
458 sys_exit(rc)
459 return rc
460}