nx_lock_reap_core.nx source
↩ module page · 117 lines · 5258 B
1// nx_lock_reap_core.nx -- importable CORE of the SOVEREIGN stale-lock reaper (R-ORCH-2a; the
2// BUILD(missing) gap the triage flagged + the exact class that blocked commits this session, now
3// mechanized as an ORGAN instead of the ps|grep|rm shell sin). A workstream that crashes mid-write
4// can leave a stale lock (git index.lock, a WMS lease, cp_deploy.lease, a reconcile lock) blocking
5// every sibling -- exactly what the orchestration north-star must never let a crash cost. This
6// reaps such a lock, but ONLY when it is provably abandoned.
7//
8// FAIL-SAFE BY CONSTRUCTION (the load-bearing property, gate-proven): reap iff the lock EXISTS AND
9// no OWNER process is alive (a /proc cmdline scan for the owner needle -- authoritative for same-
10// kernel NAS/WSL processes) AND it is older than the age threshold. A live-owned lock is NEVER
11// reaped (even if old); a fresh lock is NEVER reaped (a legit in-flight op). Default = do nothing.
12// (Cross-boundary note: a Windows git.exe holding /mnt/c/.git/index.lock is NOT visible in WSL
13// /proc; that case is closed by the sovereign-commit path, not this reaper -- honest scope.)
14// license_tier: ORIGINAL
15import "nx_syscalls.nx"
16import "nx_crashresume_census_core.nx" // ccz_read / ccz_mtime / ccz_slen / ccz_num_at / ccz_cat_*
17const K_MAGIC_65536: i64 = 65536
18const K_MAGIC_8192: i64 = 8192
19
20// unlinkat(AT_FDCWD, path, 0): x86_64 nr 263 passed DIRECTLY (the fsync-74/fstatat-262 precedent).
21func lr_unlink(path: *u8) -> i64 { return __syscall(263, AT_FDCWD, path, 0, 0, 0, 0) }
22
23// exists? (fstatat succeeds)
24func lr_exists(path: *u8) -> i64 {
25 let sb: *u8 = sys_mmap(256)
26 if sys_fstatat(path, sb) < 0 { return 0 }
27 return 1
28}
29
30// age in seconds from mtime; -1 if absent.
31func lr_age_s(path: *u8, now: i64) -> i64 {
32 let mt: i64 = ccz_mtime(path)
33 if mt < 0 { return 0 - 1 }
34 return now - mt
35}
36
37// case-sensitive substring containment (cmdline has NUL separators; needle has no NUL so it's safe).
38func lr_contains(hay: *u8, hn: i64, needle: *u8) -> i64 {
39 let nn: i64 = ccz_slen(needle)
40 if nn == 0 { return 0 }
41 var i: i64 = 0
42 while i + nn <= hn {
43 var k: i64 = 0
44 var ok: i64 = 1
45 while k < nn { if hay[i+k] != needle[k] { ok = 0; k = nn } k = k + 1 }
46 if ok == 1 { return 1 }
47 i = i + 1
48 }
49 return 0
50}
51
52// self pid via /proc/self/stat leading digits.
53func lr_selfpid() -> i64 {
54 let b: *u8 = sys_mmap(256)
55 let n: i64 = ccz_read("/proc/self/stat" as *u8, b, 255)
56 if n <= 0 { return 0 - 1 }
57 let ep: *i64 = sys_mmap(16) as *i64
58 return ccz_num_at(b, n, 0, ep)
59}
60
61// is a live process (other than self, and other than the reaper organ) whose /proc/<pid>/cmdline
62// contains `needle` currently running? Authoritative for same-kernel processes.
63func lr_owner_alive(needle: *u8) -> i64 {
64 let nn: i64 = ccz_slen(needle)
65 if nn == 0 { return 0 }
66 let self: i64 = lr_selfpid()
67 let fd: i64 = sys_openat_rd("/proc" as *u8)
68 if fd < 0 { return 0 }
69 let dbuf: *u8 = sys_mmap(K_MAGIC_65536)
70 let path: *u8 = sys_mmap(256)
71 let clbuf: *u8 = sys_mmap(K_MAGIC_8192)
72 let ep: *i64 = sys_mmap(16) as *i64
73 var found: i64 = 0
74 var run: i64 = 1
75 while run == 1 {
76 let n: i64 = sys_getdents64(fd, dbuf, K_MAGIC_65536)
77 if n <= 0 { run = 0 } else {
78 var off: i64 = 0
79 while off < n {
80 let rec: *u8 = ((dbuf as i64 + off) as *u8)
81 let reclen: i64 = dirent_reclen(rec)
82 if reclen <= 0 { off = n } else {
83 let name: *u8 = dirent_name(rec)
84 if name[0] >= (48 as u8) { if name[0] <= (57 as u8) {
85 let pid: i64 = ccz_num_at(name, ccz_slen(name), 0, ep)
86 if pid != self {
87 var o: i64 = 0
88 let pre: *u8 = "/proc/" as *u8
89 var a: i64 = 0
90 while pre[a] != (0 as u8) { path[o] = pre[a]; o = o + 1; a = a + 1 }
91 a = 0
92 while name[a] != (0 as u8) { path[o] = name[a]; o = o + 1; a = a + 1 }
93 let suf: *u8 = "/cmdline" as *u8
94 a = 0
95 while suf[a] != (0 as u8) { path[o] = suf[a]; o = o + 1; a = a + 1 }
96 path[o] = 0 as u8
97 let cln: i64 = ccz_read(path, clbuf, K_MAGIC_8192)
98 if cln > 0 { if lr_contains(clbuf, cln, needle) == 1 { found = 1; run = 0; off = n } }
99 }
100 } }
101 off = off + reclen
102 }
103 }
104 }
105 }
106 sys_close(fd)
107 return found
108}
109
110// THE decision. Pure. reap iff exists AND not owner-alive AND age > threshold. Everything else -> 0.
111func lr_should_reap(exists: i64, owner_alive: i64, age_s: i64, max_age_s: i64) -> i64 {
112 if exists == 0 { return 0 }
113 if owner_alive == 1 { return 0 } // a live owner holds it -> NEVER reap
114 if age_s < 0 { return 0 } // unknown age -> fail safe
115 if age_s <= max_age_s { return 0 } // fresh -> could be a legit in-flight op
116 return 1
117}