From 91c33a70c04fb76dab6a902e8063ebe79e47d521 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Sun, 4 Oct 2026 16:58:56 +0000 Subject: [PATCH] Build and measurement lock for agents on the Mac; the standing rule in CLAUDE.md Co-Authored-By: Claude Fable 5.1 --- tools/lock/with-lock.sh | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100755 tools/lock/with-lock.sh diff --git a/tools/lock/with-lock.sh b/tools/lock/with-lock.sh new file mode 100755 index 000000000..ca78406b2 --- /dev/null +++ b/tools/lock/with-lock.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# Serialises the two things that must not overlap on this Mac: BUILDS (cargo, swiftc, zigbuild, large cross-compiles) and +# MEASUREMENTS (test networks, hash-rate samples, simulators, anything whose numbers go in the bench log). +# tools/lock/with-lock.sh build one build at a time (builds also nice -n 19, 4 jobs) +# tools/lock/with-lock.sh measure one measurement at a time, and no build may start meanwhile +# Rule (4 October 2026): code and documents run in parallel; builds and measurements queue. Waits up to 2 hours. +set -euo pipefail +kind="$1"; shift +dir=/tmp/igneum-locks; mkdir -p "$dir" +case "$kind" in + build) locks=("$dir/build");; + measure) locks=("$dir/measure" "$dir/build");; + *) echo "usage: with-lock.sh build|measure " >&2; exit 2;; +esac +fds=(); i=9 +for l in "${locks[@]}"; do + i=$((i+1)); eval "exec $i>\"$l\"" + if ! python3 - "$i" "$l" <<'PY' +import fcntl, sys, time, os +fd=int(sys.argv[1]); name=sys.argv[2]; t=time.time() +while True: + try: fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB); break + except BlockingIOError: + if time.time()-t > 7200: print(f"with-lock: gave up waiting for {name} after 2 h", file=sys.stderr); sys.exit(1) + time.sleep(5) +PY + then exit 1; fi +done +echo "with-lock: holding ${locks[*]##*/} for: $*" >&2 +exec "$@"