fix(miner): guard repo-clone across sibling processes with a cross-process lockfile#7139
fix(miner): guard repo-clone across sibling processes with a cross-process lockfile#7139bitfathers94 wants to merge 1 commit into
Conversation
…ocess lockfile ensureRepoCloned's per-repo serialization (JSONbored#6762) was an in-process Map, so two fleet-mode containers sharing the same clone volume each started with an empty Map and could run git checkout/reset --hard on the same base clone at once, corrupting the working tree or tripping .git/index.lock. Take an OS-level exclusive lockfile (open(path, 'wx')) on a deterministic path beside the clone before any git mutation, held for the whole clone/fetch/ checkout/reset sequence and released on error. A losing process waits, bounded by a timeout that fails closed with repo_clone_lock_timeout; a lock left by a crashed process self-expires after a stale window (age-based reclaim, mirroring worktree-allocator.js) and is registered as a process-lifecycle cleanup resource so SIGINT/SIGTERM drops it on a clean exit (mirroring local-store.js). The in-process Map is retained, so same-process calls stay at least as safe. Closes JSONbored#7084
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7139 +/- ##
=======================================
Coverage 93.75% 93.76%
=======================================
Files 692 692
Lines 68853 68913 +60
Branches 18781 18781
=======================================
+ Hits 64556 64616 +60
Misses 3302 3302
Partials 995 995
Flags with carried forward coverage won't be shown. Click here to find out more.
|
|
Caution 🛑 LoopOver review result - reject/close recommendedReview updated: 2026-07-18 00:19:30 UTC
Review summary Blockers
Nits — 5 non-blocking
Why this is blocked
📋 Copy for AI agents — paste into your coding agentDecision drivers
Context & advisory signals — never blocks the verdict
Linked issue satisfactionAddressed Review context
Contributor next steps
Signal definitions
🧪 Chat with LoopOverAsk LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.
Full command reference: https://loopover.ai/docs/loopover-commands 🧪 Experimental — new and may change. 🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed 💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.
|
|
LoopOver is closing this pull request on the maintainer's behalf (AI reviewers agree on a likely critical defect: packages/loopover-miner/lib/repo-clone.js forceUnlinkLock/acquireRepoCloneLock: when a lock is judged stale, forceUnlinkLock unconditionally unlinks the path without re-verifying the content still matches what was read as stale, so if two waiters both read the same stale lock and race to reclaim, the second unlink can delete the FIRST winner's freshly-written live lock (written moments earlier in the same loop iteration by the first winner), after which the second waiter's next `open` also succeeds — both processes end up believing they hold the exclusive lock, defeating the cross-process guarantee this PR is meant to provide; the added tests only exercise a single acquirer reclaiming a stale lock, never two concurrent reclaimers, so this race is untested.). This is an automated maintenance action — to pursue this change, please open a new pull request with the issues resolved. Closed PRs may be analyzed later to improve review accuracy, but they are not automatically reopened or re-reviewed. |
fix(miner): guard repo-clone across sibling processes with a cross-process lockfile
ensureRepoCloned's per-repo serialization (#6762) was an in-process Map, so
two fleet-mode containers sharing the same clone volume each started with an
empty Map and could run git checkout/reset --hard on the same base clone at
once, corrupting the working tree or tripping .git/index.lock.
Take an OS-level exclusive lockfile (open(path, 'wx')) on a deterministic path
beside the clone before any git mutation, held for the whole clone/fetch/
checkout/reset sequence and released on error. A losing process waits, bounded
by a timeout that fails closed with repo_clone_lock_timeout; a lock left by a
crashed process self-expires after a stale window (age-based reclaim, mirroring
worktree-allocator.js) and is registered as a process-lifecycle cleanup
resource so SIGINT/SIGTERM drops it on a clean exit (mirroring local-store.js).
The in-process Map is retained, so same-process calls stay at least as safe.
Closes #7084