From be99cb3821fa455361ed2530425fb3bc7f20058b Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Mon, 5 Oct 2026 01:10:17 +0000 Subject: [PATCH] Lock: three run slots for functional runs; a measurement waits for all of them Co-Authored-By: Claude Fable 5.1 --- tools/lock/with-lock.sh | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tools/lock/with-lock.sh b/tools/lock/with-lock.sh index c75f7be3e..55b931251 100755 --- a/tools/lock/with-lock.sh +++ b/tools/lock/with-lock.sh @@ -5,7 +5,8 @@ # three at once use 12 of the 16 cores); waits when all are busy # tools/lock/with-lock.sh measure exclusive: waits for every build slot and blocks new builds # tools/lock/with-lock.sh run a functional run (test network, attack harness, simulator whose -# outputs are counts, locks, forks, seconds): one at a time, builds continue +# outputs are counts, locks, forks, seconds): one of THREE run slots, +# builds continue; a measurement waits for all of them # tools/lock/with-lock.sh status who holds what, and for how long # Rule (4 October 2026): code and documents run in parallel; builds share three slots; measurements are exclusive. # Evening of 4 October: one build slot and a 3-hour network run under `measure` left twelve agents queued; hence the @@ -15,7 +16,7 @@ set -euo pipefail kind="${1:-}"; shift || true dir=/tmp/igneum-locks; mkdir -p "$dir" if [ "$kind" = status ]; then - for f in measure build build-0 build-1 build-2; do + for f in measure build build-0 build-1 build-2 run-0 run-1 run-2; do [ -e "$dir/$f" ] || continue holder=$(python3 - "$dir/$f" <<'PY' import fcntl, sys, os @@ -70,10 +71,22 @@ if mode == 'build': if got[0] != k: os.close(fd) held = [(f"build-{got[0]}", got[1])] elif mode == 'measure': - for name in ['measure', 'build', 'build-0', 'build-1', 'build-2']: + for name in ['measure', 'build', 'build-0', 'build-1', 'build-2', 'run-0', 'run-1', 'run-2']: fd = opened(name); wait_lock(fd, name); held.append((name, fd)) else: - fd = opened('measure'); wait_lock(fd, 'measure'); held.append(('measure', fd)) + # run: one of THREE run slots (functional runs on their own port ranges can overlap), none while a measurement + # holds every slot; a measurement waits for every run slot in turn + slots = [opened(f"run-{k}") for k in range(3)] + got = None + while got is None: + for k, fd in enumerate(slots): + if try_lock(fd): got = (k, fd); break + if got is None: + if time.time() - t0 > 7200: print("with-lock: gave up waiting for a run slot after 2 h", file=sys.stderr); sys.exit(1) + time.sleep(5) + for k, fd in enumerate(slots): + if got[0] != k: os.close(fd) + held = [(f"run-{got[0]}", got[1])] for name, fd in held: os.ftruncate(fd, 0); os.lseek(fd, 0, 0) os.write(fd, f"pid {os.getpid()} since {time.strftime('%H:%M:%S', time.gmtime())}Z waited {int(time.time()-t0)} s: {' '.join(cmd)[:120]}\n".encode())