code wiki / (root) / nx_lock_reap.nx

nx_lock_reap.nx source

↩ module page · 61 lines · 3239 B

1// nx_lock_reap.nx -- CLI of the sovereign stale-lock reaper (R-ORCH-2a). Reaps ONE abandoned lock 2// so a crashed workstream never blocks its siblings -- the janitorial pillar of the orchestration 3// north-star, as an organ (never the ps|grep|rm shell sin). 4// usage: nx_lock_reap <lockpath> <max_age_s> <owner_needle> [dry] 5// owner_needle = a substring of the owner process's /proc cmdline (e.g. "nx_mgmt_api", "git"); 6// pass "-" for no owner-check (age-only, for cross-boundary locks where /proc can't see the owner). 7// Reaps iff exists AND owner not alive AND age > max_age_s. dry -> report only. Always exits 0 8// (a reaper must never fail its cron); appends a line to knowledge/status/lock_reap.log. 9// license_tier: ORIGINAL expect_exit: 0 10import "nx_syscalls.nx" 11import "nx_lock_reap_core.nx" 12const K_MAGIC_1024: i64 = 1024 13 14func r_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 15func r_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 16 17func main(argc: i64, argv: *i64) -> i64 { 18 if argc < 4 { r_puts("usage: nx_lock_reap <lockpath> <max_age_s> <owner_needle|-> [dry]\n" as *u8); return 0 } 19 let lockpath: *u8 = argv[1] as *u8 20 let ep: *i64 = sys_mmap(16) as *i64 21 let maxage: i64 = ccz_num_at(argv[2] as *u8, ccz_slen(argv[2] as *u8), 0, ep) 22 let needle: *u8 = argv[3] as *u8 23 var dry: i64 = 0 24 if argc >= 5 { if r_streq(argv[4] as *u8, "dry" as *u8) == 1 { dry = 1 } } 25 26 let now: i64 = sys_now_realtime_sec() 27 let exists: i64 = lr_exists(lockpath) 28 var owner: i64 = 0 29 if r_streq(needle, "-" as *u8) == 0 { if exists == 1 { owner = lr_owner_alive(needle) } } 30 let age: i64 = lr_age_s(lockpath, now) 31 let decide: i64 = lr_should_reap(exists, owner, age, maxage) 32 33 let line: *u8 = sys_mmap(K_MAGIC_1024) 34 var o: i64 = 0 35 o = ccz_cat_str(line, o, "LOCKREAP path=" as *u8) 36 o = ccz_cat_str(line, o, lockpath) 37 o = ccz_cat_str(line, o, " exists=" as *u8) 38 o = ccz_cat_num(line, o, exists) 39 o = ccz_cat_str(line, o, " owner_alive=" as *u8) 40 o = ccz_cat_num(line, o, owner) 41 o = ccz_cat_str(line, o, " age_s=" as *u8) 42 o = ccz_cat_num(line, o, age) 43 o = ccz_cat_str(line, o, " max=" as *u8) 44 o = ccz_cat_num(line, o, maxage) 45 o = ccz_cat_str(line, o, " -> " as *u8) 46 if decide == 1 { 47 if dry == 1 { o = ccz_cat_str(line, o, "WOULD-REAP (dry)" as *u8) } else { 48 let rc: i64 = lr_unlink(lockpath) 49 if rc == 0 { o = ccz_cat_str(line, o, "REAPED (stale, unowned)" as *u8) } else { o = ccz_cat_str(line, o, "REAP-FAILED" as *u8) } 50 } 51 } else { 52 if exists == 0 { o = ccz_cat_str(line, o, "NO-LOCK" as *u8) } else { 53 if owner == 1 { o = ccz_cat_str(line, o, "HELD (owner alive -- fail-safe, no reap)" as *u8) } else { o = ccz_cat_str(line, o, "TOO-FRESH (fail-safe, no reap)" as *u8) } 54 } 55 } 56 o = ccz_cat_str(line, o, "\n" as *u8) 57 sys_write(1, line, o) 58 let lfd: i64 = sys_openat_append("knowledge/status/lock_reap.log" as *u8, 420) 59 if lfd >= 0 { sys_write(lfd, line, o); sys_close(lfd) } 60 return 0 61}