-
Notifications
You must be signed in to change notification settings - Fork 1.7k
cargo metadata
call alters lockfile despite --frozen
r-a cargo configuration
#19729
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
Comments
The Iirc the main reason why we don't pass |
Any advice on how to avoid the torn read race condition? It's really vexing (and raises security teams' eyebrows) when a user's Would it be possible, say, to have r-a run |
Back off seems problematic to me (implementation/complexity wise). So a config would be an option. Alternatively I wonder if the error message cargo gives for when the invocation fails due to |
I think those are good options. Just checking my intuition: let's say in either way we make r-a not update the lockfile. Then:
In this case, my slight preference from a workflow UX perspective would be for not popping up a notification, because the issue fixed itself already. So I'd personally prefer the config option. But like I said, both options you mentioned are strongly preferable over the status quo. I'd be happy with either. Thanks again! |
So I was talking a bit with people at RustWeek, turns out there should be a fairly simple fix to this. We should just debounce the metadata call by 50-100ms after the last file change notification. That way we should be deferring things until git is done. |
rust-analyzer version:
0.3.2441-standalone (d8887c0758 2025-04-26)
rustc version: `rustc 1.85.1 (4eb161250 2025-03-15)
editor or extension: Cursor v0.49.6 based on VSCode 1.96.2 + official
rust-lang.rust-analyzer
extension version0.3.2441
relevant settings: VSCode workspace settings file containing
What I expected to happen: r-a cannot cause
Cargo.lock
changes, due to"rust-analyzer.cargo.extraArgs": ["--frozen"]
What actually happens: r-a occasionally causes
Cargo.lock
changes, due to acargo metadata
call that doesn't supply--frozen
How I verified this is from r-a and not something else:
cargo
with a shim that logs full invocationscargo metadata --format-version 1 --manifest-path /path/to/Cargo.toml --filter-platform <my-platform>
— note this did not include the configured--frozen
Cargo.lock
How this happens in the real world
In the real-world this happens due to a "torn read" race condition versus
git checkout
. I'll describe the real-world situation first for intuition-building purposes, then offer a way to simulate the outcome of the race for easier debugging.Consider a large repo where a
git checkout
may take a noticeable amount of time. Say we move from a newer branch to an older one, where the newer branch had updated some dependencies and picked up new ones.git checkout <older-branch>
Cargo.toml
becomes updated but the matchingCargo.lock
change isn't applied yet — git is busy updating other files and hasn't gotten to it yetcargo metadata
without--frozen
, despite the configuration (as mentioned above)"rust-analyzer.cargo.targetDir": true
means the lockfile isn't locked during this processcargo metadata
readsCargo.toml
andCargo.lock
, and continues running (A)cargo metadata
is in flight, the git checkout updatesCargo.lock
(B)cargo
notices that it's getting a different resolution: some of the dependencies present in theCargo.lock
it read at (A) are superfluous, so it rewritesCargo.lock
to exclude them — but it leaves the updated versions of other still-used dependencies (C)Cargo.lock
at (B) is overwritten by (C)At this point, both the checkout and the r-a run are complete. A subsequent
git status
showsCargo.lock
has newer versions of some dependencies — a hybrid lockfile between the newer and older branch.Simulating the torn read
The easiest way to simulate the race is:
r-a origin of the
cargo metadata
callAFAICT the
cargo metadata
invocation in question is coming from this block, which explicitly passeslocked: false
. There's a similar block above it, for therustc_dir
case when there's a custom sysroot, which might also be similarly affected — I'm not sure.Happy to provide any more info or help however I can. Thanks for looking into this!
The text was updated successfully, but these errors were encountered: