Drop the unreachable re-entry guard from _repo_lock - #326
anandhu-eng wants to merge 1 commit into
Conversation
|
MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅ |
🤖 AI PR Review SummaryThis PR removes the previously used thread-local set for tracking held repo locks and the reentrancy logic in _repo_lock, simplifying the locking mechanism. Instead, it relies on _repo_pull_lock to guard against same-thread recursive pulls. The comments have been updated to clarify the locking behavior and limitations. The test for same-thread reentry deadlock was removed, reflecting the change in locking strategy. Overall, the changes reduce complexity but remove the within-thread reentrancy in _repo_lock, which may affect code relying on that behavior. The tests verify that locks are released properly and that dependency cycles are guarded by _repo_pull_lock. No new inline actionable issues found in the diff. |
54f451e to
2689a33
Compare
2689a33 to
fe5e5e4
Compare
_repo_lock kept a thread-local set (_held_repo_locks) so a thread could re-enter a repo lock it already held. That case can no longer happen: _repo_pull_lock checks _pulling_repos first and skips the nested pull, and a path is in _held_repo_locks only while it is also in _pulling_repos. The other caller, RepoAction.rm(), never runs inside a pull. Remove the set and make _repo_lock a plain lock, leaving _pulling_repos as the single same-thread guard. Move the note about crossed dependencies between threads onto _pulling_repos, and fix comments that described re-entry as a no-op. Tests: drop test_same_thread_reentry_does_not_self_deadlock, which only exercised the removed branch. test_dependency_cycle_does_not_recurse now also asserts the nested entry does not block; it fails with a lock Timeout if the remaining guard is removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
fe5e5e4 to
25106f4
Compare
Stack: #265 ← #323 ← #325 ← #326. Merge in that order: #323 into #265's branch first, then each next PR. This PR targets #325's branch. All 125 tests pass at the top of the stack.
Why
#265 has two thread-local sets that both mean "this thread already has this repo":
_held_repo_locks(in_repo_lock)_pulling_repos(in_repo_pull_lock){'return': 0}Both came from #303. The first fixed a self-deadlock:
register_repopulls each dependency while the parent repo's lock is held, and a secondFileLockon the same file blocks even within one thread. But that fix turned a dependency cycle into infinite recursion, so the second set was added to skip the nested pull.The first set is now unreachable:
_repo_pull_lockchecks_pulling_reposbefore it calls_repo_lock, and a path is only in_held_repo_lockswhile it is also in_pulling_repos._repo_lock's only other caller,RepoAction.rm(), never runs inside a pull._repo_lockdirectly. No pull or rm test notices.Changes
_repo_lockis now a plain lock._held_repo_locksand_repo_locks_held_by_this_threadare removed._pulling_repos. Comments that described same-thread re-entry as a no-op are corrected.test_same_thread_reentry_does_not_self_deadlockis removed. It only exercised the deleted branch.test_dependency_cycle_does_not_recursenow also asserts that the nested entry doesn't block. With the remaining guard removed it fails with a lockTimeout, which I checked.No behaviour change. Locally: 120 unit tests pass, plus
.github/scripts/test_repo_pull_force.py.🤖 Generated with Claude Code