-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix race condition in local registry crate unpacking #6591
Conversation
Copy crate and keep exclusive lock to it with local registries. Ensures that only one instance will try to extract the source of a new package. Fixes rust-lang#6588.
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @dwijnand (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
src/cargo/sources/registry/local.rs
Outdated
let meta = dst.file().metadata()?; | ||
if meta.len() > 0 { | ||
return Ok(MaybeLock::Ready(dst)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is directly copied from RemoteRegistry
. Probably not necessary, though I'm wondering how necessary it is in the current version of RemoteRegistry
anyway.
(Sorry, travelling) |
Thanks for the PR! I'm may be confused though as I'm not sure how the original implementation here suffered from a bug. In the original implementation it's just calculating the checksum for a tarball, so I'm not sure where the race is for concurrent builds? |
The race is in the unpacking, I think. I think a better solution might be to actually lock the unpacking instead of the tarball. This could be fairly easily done by locking the |
I'm trying to make sense of this, but I don't think this PR as-is is the right solution. It looks like unpacking is actually already racy even for remote downloads because the unpacking step isn't synchronized at all. We do some synchronization to ensure that only one Cargo downloads the crate during remote downloads, but even for remote downloads a shared read lock can be returned (as expected local registries always do). Looking at the original bug report again it looks like there's a bug in Cargo's error reporting, because there should be an I/O error in the error message as to what actually failed in the underlying system. Currently it just shows that something failed to unpack, but it doesn't say why (or what os error hapened). Perhaps the locking here could be moved to the unpacking step instead of the downloading step? |
I've spent some more time on this and I think I understand a lot better what the issue is now. Imagine two instances trying to use a package that is not yet unpacked:
This only happens when using a local registry. With a remote registry the registry index gets locked, allowing only one instance at a time to access the registry cache. I was able to reproduce this by:
My latest commit fixes the issue locally. |
That sounds right to me, and the fix looks almost there! The only other thing I think we need to handle is that
I think we'll want to start with an |
@bors: r+ Looks great to me, thanks! |
📌 Commit a23612d has been approved by |
⌛ Testing commit a23612d with merge cbc159917ec4350853e241d0aa8f52950dfd4ea4... |
💥 Test timed out |
@bors retry |
⌛ Testing commit a23612d with merge a15852c386d9566d242a80cbb58dc94e54f9e764... |
💥 Test timed out |
@bors retry |
@hugwijst: 🔑 Insufficient privileges: not in try users |
@bors retry |
Fix race condition in local registry crate unpacking Copy crate and keep exclusive lock to it with local registries. Ensures that only one instance will try to extract the source of a new package. Fixes #6588.
☀️ Test successful - checks-travis, status-appveyor |
Update cargo 7 commits in 245818076052dd7178f5bb7585f5aec5b6c1e03e..4e74e2fc0908524d17735c768067117d3e84ee9c 2019-01-27 15:17:26 +0000 to 2019-02-02 17:48:44 +0000 - Fix overlapping progress with stdout. (rust-lang/cargo#6618) - Improve progress bar flickering. (rust-lang/cargo#6615) - Add detail to multiple rename deps (rust-lang/cargo#6603) - Fix race condition in local registry crate unpacking (rust-lang/cargo#6591) - Revert "Make incremental compilation the default for all profiles." (rust-lang/cargo#6610) - Fixup the docs on crate-type (rust-lang/cargo#6606) - Document that owner --add now just invites (rust-lang/cargo#6604)
Copy crate and keep exclusive lock to it with local registries. Ensures
that only one instance will try to extract the source of a new package.
Fixes #6588.