Preserve stable params lock ownership - #116
Open
FrogAi wants to merge 1 commit into
Open
Conversation
FrogAi
force-pushed
the
codex/stabilize-params-locking
branch
from
August 10, 2026 02:58
edaa76f to
4a8942f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Developer summary
PutParamandRemoveParamcurrently unlink the shared.lockpathname while its inode may still be locked. Another process can then create and lock a different inode at the same path, entering the protected section concurrently. The same paths also leave temporary-file and directory descriptors to garbage collection.This keeps the lock pathname stable, preserves the existing bounded retry policy, and closes each owned descriptor deterministically. The change stays inside
params/params.goand does not alter exported APIs or normal parameter contents.Verification
main; this branch returns the existing lock-acquisition error without changing the parameter.go test, race, vet, and build pass repository-wide on Linux/Go 1.25.1.Compatibility
Parameter paths, payload bytes, atomic rename ordering, file/directory
fsyncordering, retry count, retry delay, and exported APIs are unchanged. The lock file now persists and requests the same creation mode as FrogPilot's C++ owner.Engineering record and audit trail
Root cause
Both persistence operations repeatedly call
TryLockon the shared parent.lock. After the 31st failed attempt, current code removes that pathname and retries. It also removes the pathname after a successful acquisition, before the deferred unlock runs.On Linux, unlinking a pathname does not release an advisory lock held through an open file descriptor. A later opener can create a new file at the same pathname, lock its different inode, and enter the critical section while the original lock remains held.
PutParamalso leaves its temporary-file descriptor open afterfsync, and both operations leave their synced directory descriptors open. Error paths after temporary-file creation have the same ownership gap.Implementation
0775when the lock file is first created, matching the C++ owner of the same path.fsyncand before lock acquisition/rename.fsync.The pinned
gofrs/flockimplementation releases and closes its held descriptor whenUnlocksucceeds. Existing lock files are opened without truncation.Red/green behavior
1daead9.lockthrough the retry windowcould not obtain lock; target is unchanged12 -> 204(+192)7 -> 7(+0)The 192-descriptor increase is the exact ownership total for the exercised sequence: each put retained one temporary-file descriptor and one directory descriptor, and each remove retained one directory descriptor.
Final validation
The external matrix exercises the exported
PutParamandRemoveParamfunctions in temporary Linux parameter trees. The final rebased production tree passed:-count=10go test ./...go test -race ./...go vet ./...go build ./...git diff --checkScope limits
The runtime matrix establishes Linux advisory-lock exclusion with a separate helper process and normal descriptor ownership through
/proc/self/fd. It does not establish identical semantics on every OS, inject kernelclose/fsync/LOCK_UNfailures, redesign contention timing, or measure production contention frequency. ExistingRemoveParamunlink-error handling and settings-save ordering are outside this change.