Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ All notable changes to RigForge are documented here. The format is based on

## [Unreleased]

### Fixed

- **rig-lock survives a non-root reserve (#242).** The shared `rig_lock` helper now opens
`/var/lock/rig-e2e.lock` read-only (`9<`) instead of write (`9>`). A lock file first created by a
non-root `flock` (a manual reserve after a reboot clears the `/run/lock` tmpfs) is owned by that
user, and `fs.protected_regular=2` then blocked even root's `O_CREAT`-write of it with EACCES,
aborting the release perf gate until someone `rm`ed the file. A read-open is never guarded and
`flock` works fine on a read fd, so this sidesteps it without ever removing a possibly-held lock.
The `~/README.md` box contracts also now say to reserve as root. Test-infra only.

## [1.7.0] - 2026-07-11

### Added
Expand Down
11 changes: 9 additions & 2 deletions tests/e2e-pithead.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,15 @@ die() {
rig_lock() { # rig_lock <project> <suite> [shared]
local mode=-x
[ "${3:-}" = shared ] && mode=-s
exec 9>"${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}"
chmod 666 "${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" 2>/dev/null || true # a non-root shared reader can join later
local lf="${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}"
# Open the lock READ-only (9<). A lock file first created by a NON-root flock (a manual reserve
# after a reboot clears the /run/lock tmpfs) is owned by that user, and fs.protected_regular then
# blocks even root's O_CREAT-*write* of it (a 9> open) with EACCES. A read-open is never guarded,
# and flock -x/-s works fine on a read fd, so this sidesteps it without rm-ing a possibly-held
# lock. Create it first if absent; keep it 0666 so a shared reader can still join. (#242)
[ -e "$lf" ] || : >"$lf" 2>/dev/null || true
chmod 666 "$lf" 2>/dev/null || sudo chmod 666 "$lf" 2>/dev/null || true
exec 9<"$lf"
if ! flock -n $mode 9; then
if [ "${RIG_LOCK_WAIT:-0}" = 1 ]; then
echo "rig busy ($(cat "${RIG_LOCK_HOLDER:-/run/rig-e2e.holder}" 2>/dev/null || echo unknown)) — waiting..." >&2
Expand Down
11 changes: 9 additions & 2 deletions tests/e2e-real.sh
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,15 @@ die() {
rig_lock() { # rig_lock <project> <suite> [shared]
local mode=-x
[ "${3:-}" = shared ] && mode=-s
exec 9>"${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}"
chmod 666 "${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}" 2>/dev/null || true # a non-root shared reader can join later
local lf="${RIG_LOCK_FILE:-/var/lock/rig-e2e.lock}"
# Open the lock READ-only (9<). A lock file first created by a NON-root flock (a manual reserve
# after a reboot clears the /run/lock tmpfs) is owned by that user, and fs.protected_regular then
# blocks even root's O_CREAT-*write* of it (a 9> open) with EACCES. A read-open is never guarded,
# and flock -x/-s works fine on a read fd, so this sidesteps it without rm-ing a possibly-held
# lock. Create it first if absent; keep it 0666 so a shared reader can still join. (#242)
[ -e "$lf" ] || : >"$lf" 2>/dev/null || true
chmod 666 "$lf" 2>/dev/null || sudo chmod 666 "$lf" 2>/dev/null || true
exec 9<"$lf"
if ! flock -n $mode 9; then
if [ "${RIG_LOCK_WAIT:-0}" = 1 ]; then
echo "rig busy ($(cat "${RIG_LOCK_HOLDER:-/run/rig-e2e.holder}" 2>/dev/null || echo unknown)) — waiting..." >&2
Expand Down
16 changes: 16 additions & 0 deletions tests/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5435,6 +5435,22 @@ else
assert_eq "queued waiter actually acquired (#183)" \
"$([ -f "$RLD/got.q" ] && echo acquired || echo blocked)" "acquired"

# #242: the lock is opened READ-only, so a pre-existing lock file (a leftover a non-root
# reserve created earlier) is acquired without needing to O_CREAT-write it — which is what
# dodges fs.protected_regular's block on root re-opening a non-root-created file in /run/lock.
RIG_LOCK_FILE="$RLD/pre" RIG_LOCK_HOLDER="$RLD/pre.holder"
: >"$RIG_LOCK_FILE" # pre-exists before any rig_lock call
(eval "$RL_SRC" && rig_lock rigforge pre-existing "" && touch "$RLD/pre.ok") 2>/dev/null
assert_eq "acquires a pre-existing lock file (#242)" "$([ -f "$RLD/pre.ok" ] && echo y || echo n)" "y"
# A lock file left at a restrictive mode is normalized and still acquired (the root+sticky
# protected_regular sidestep itself — read-open of a non-root-created file — needs a live root
# rig and is covered by the e2e gate, not this sandbox).
RIG_LOCK_FILE="$RLD/ro" RIG_LOCK_HOLDER="$RLD/ro.holder"
: >"$RIG_LOCK_FILE" && chmod 444 "$RIG_LOCK_FILE"
(eval "$RL_SRC" && rig_lock rigforge restrictive "" && touch "$RLD/ro.ok") 2>/dev/null
assert_eq "normalizes + acquires a restrictive-mode lock file (#242)" "$([ -f "$RLD/ro.ok" ] && echo y || echo n)" "y"
chmod 666 "$RLD/ro" 2>/dev/null || true

unset RIG_LOCK_FILE RIG_LOCK_HOLDER
fi

Expand Down