code wiki / _hdl_build / nx_tool_run_timeout_gate.nx
nx_tool_run_timeout_gate.nx
buildroot/runtime/_hdl_build/nx_tool_run_timeout_gate.nx
about
nx_tool_run_timeout_gate.nx -- proves tr_run_capture_to actually BOUNDS a hanging child (seq1412).
The claim under test is not "the function returns a timeout constant" -- that is trivial to fake. It is
"a child that would run for 10 seconds is KILLED at the deadline, its output is still captured, it is
REAPED rather than orphaned, and a fast child is NOT falsely timed out". So every tooth measures
something an empty implementation would fail:
T1 the deadline FIRES -- 10s sleeper, 500ms budget -> TR_ERR_TIMEOUT
T2 the deadline is REAL TIME -- that call returns in well under the sleeper's 10s (the load-bearing
tooth: returning -5 after waiting the full 10s would be a lie)
T3 NEG-CONTROL fast child -- a 50ms sleeper with a 5s budget exits 0, NOT timed out
T4 output survives -- the fast child's stdout is captured intact
T5 REPEATABLE -- a second timeout run behaves identically; resource-leak
accounting requires separate lifecycle evidence
T6 opt-out is explicit -- timeout_ms<=0 delegates to the unbounded path and still succeeds
license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0
dependencies 4 imports · 0 importers
imports: nx_syscalls.nxnx_tool_run.nxnx_os_proc.nxnx_gate_verdict.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 24 | const TG_RLIMIT_NOFILE: i64 = 7 |
| 26 | const TG_HIGH_FD_WITNESS: i64 = 2048 |
| 27 | const TG_CHILDREN_READ_WINDOW: i64 = 4096 |
| 29 | const TG_STDOUT: i64 = 1 |
| 30 | const TG_SLEEPER: *u8 = "_build/nx_tr_sleeper.sov.elf" |
| 31 | const TG_OUTCAP: i64 = 65536 |
| 34 | const TG_HANG_MS: i64 = 10000 |
| 35 | const TG_BUDGET_MS: i64 = 500 |
| 38 | const TG_MAX_ELAPSED_S: i64 = 5 |
| 39 | const TG_FAST_MS: i64 = 50 |
| 40 | const TG_FAST_BUDGET_MS: i64 = 5000 |
| 77 | const TG_STREAM_CAP: i64 = 16384 |
| 78 | const TG_STREAM_BLOCKS: i64 = 16 |
| 79 | const TG_STREAM_EXIT: i64 = 23 |
| 80 | const TG_SYS_GETPID: i64 = 172 // portable syscall ABI used by nx_getpid_const_probe |
| 247 | const TG_PARALLEL_SMALL: i64=8 |
| 248 | const TG_PARALLEL_LARGE: i64=15 |
| 249 | const TG_PARALLEL_ROW: i64=8 |
| 468 | const TG_LIFETIME_WAIT_MS: i64 = 10 |
| 469 | const TG_LIFETIME_ATTEMPTS: i64 = 50 |
functions
| 42 | func tg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(TG_STDOUT, s, n); return 0 } called by 5: tg_checktg_parallel_capturetg_high_descriptor_subjecttg_lifecycle_gatemain calls 1: sys_write |
| 43 | func tg_num(v: i64) -> i64 called by 5: tg_checktg_parallel_capturetg_high_descriptor_subjecttg_lifecycle_gatemain calls 2: sys_writesys_mmap |
| 56 | func tg_check(ok: i64, label: *u8, got: i64, want: i64) -> i64 |
| 68 | func tg_run(ms: *u8, budget: i64, out: *u8, ol: *i64) -> i64 |
| 81 | func tg_stream_child(mode: i64) -> i64 |
| 111 | func tg_stream_check(self: *u8, mode: *u8, traced: i64, wantcut: i64, wantlen: i64) -> i64 |
| 142 | func tg_stream_timeout(self: *u8) -> i64 |
| 159 | func tg_invalid_capacity() -> i64 |
| 173 | func tg_descendant_deadline(self: *u8) -> i64 |
| 189 | func tg_lifecycle_exit(self: *u8, mode: *u8, budget: i64, expected: i64) -> i64 |
| 204 | func tg_wait_observe() -> i64 |
| 226 | func tg_cwd_check(self: *u8, mode: *u8, cwd: *u8, expected: i64) -> i64 |
| 250 | func tg_parallel_producer(identity: i64) -> i64 |
| 268 | func tg_parallel_worker(self: *u8, index: i64, row: *i64) -> i64 |
| 294 | func tg_parallel_capture(self: *u8, count: i64) -> i64 |
| 361 | func tg_resource_finish(pid: i64, baseline: i64) -> i64 called by 2: tg_lifecycle_gatemain calls 9: tg_checkosp_fd_countsys_mmapsys_pipe2sys_closesys_openat_rd+3 |
| 395 | func tg_high_descriptor_subject(self: *u8) -> i64 called by 1: tg_high_descriptor calls 18: sys_openat_rdtg_checksys_dup3sys_closesys_mmapnx_prlimit+12 |
| 440 | func tg_high_descriptor(self: *u8) -> i64 called by 2: tg_lifecycle_gatemain calls 5: sys_mmapnx_prlimittg_checktg_high_descriptor_subjectsys_munmap |
| 470 | func tg_lifetime_fixture(late: i64) -> i64 called by 1: tg_lifetime_check calls 16: sys_prctlsys_mmap_sharedsys_mmapsys_pipe2sys_forksys_close+10 |
| 541 | func tg_lifetime_check(late: i64) -> i64 called by 2: tg_lifecycle_gatemain calls 7: sys_forktg_lifetime_fixturesys_exitsys_mmaptr_reapwait_status_rc+1 |
| 555 | func tg_owner_children(owner: i64, pids: *i64) -> i64 |
| 558 | func tg_capture_owner_crash(self: *u8, incomplete: i64) -> i64 called by 1: tg_capture_crash_check calls 11: sys_prctlsys_forksys_mmaptr_run_capture_tosys_exittg_owner_children+5 |
| 620 | func tg_capture_crash_check(self: *u8, incomplete: i64) -> i64 called by 2: tg_lifecycle_gatemain calls 7: sys_forktg_capture_owner_crashsys_exitsys_mmaptr_reapwait_status_rc+1 |
| 636 | func tg_lifecycle_gate(self: *u8) -> i64 called by 1: main calls 9: osp_fd_counttg_capture_crash_checktg_lifetime_checktg_high_descriptortg_resource_finishtg_puts+3 |
| 649 | func main(argc: i64, argv: *i64) -> i64 |