Skip to content

fix: race condition in update lock lets two updates run at once#27

Open
Adityakk9031 wants to merge 2 commits into
AlmanacCode:mainfrom
Adityakk9031:#26
Open

fix: race condition in update lock lets two updates run at once#27
Adityakk9031 wants to merge 2 commits into
AlmanacCode:mainfrom
Adityakk9031:#26

Conversation

@Adityakk9031

@Adityakk9031 Adityakk9031 commented Jul 10, 2026

Copy link
Copy Markdown

close:#26
The update lock had a classic TOCTOU bug. When the lock was stale, the code would:

  1. Check it's stale
  2. Delete it
  3. Loop back and try open("x") again
    Between step 2 and 3, another process could grab the lock. Now both processes think they own it, so both fire off uv tool upgrade or pip install at the same time. Corrupts the install.

The fix uses os.replace() to atomically swap in the new lock — no window between removing the old one and planting the new one. Also added a read-back safety check: after the replace, we verify our PID is still in the file. If another process raced past us, we detect it and back off.

Tests cover all the paths: fresh lock, non-stale refusal, stale replacement, and the race-lost scenario.

@divitsheth divitsheth left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for raising this issue. Using an atomic replacement moves the solution in the right direction but there is one remaining gap. Process A can replace the lock and confirm ownership, but process B can then replace it and also confirm ownership. Both could still proceed with the update.

could you replace the PID-based ownership check with filelock.FileLock and hold that lock inside UpdateLockLease for the full update? Please add filelock as a direct dependency. This gives us OS-backed locking on macOS, Linux, and Windows, with automatic release when the process exits.
It would also help to add a multiprocessing test where process A holds the lock and process B cannot acquire it. The current mocked test returns during the stale check before exercising the replacement race.
Thanks again. This is close and just needs the final ownership guarantee before merging.

@Adityakk9031

Copy link
Copy Markdown
Author

ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants