-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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 Pkg.free() so that it never removes the specified package #24048
Conversation
This test is supposed to fail on Windows only. Fix is coming.
On Windows, libgit2 can hold locks on files under the package directory which resolve() might want to remove, leading to corruption.
No need to duplicate code here. It turns out the multi-package method taking a collection was actually correct, as it called resolve() only after freeing libgit2 handles.
Else, resolve() will remove the package (potentially losing data), which is unlikely to be the intended effect.
First commit failed on Windows with the expected error. Second commit passed the tests as it should. Third commit is a more radical version which essentially does the same thing, but removes duplicated methods. The fourth commit attempts actually fixing #17994 by always adding the specified package to REQUIRE so that it's never removed. This sounds like a good idea since it's unlikely that the user intended to remove that package by calling |
But wouldn't put a package in REQUIRE will make it permanent even if the user accidentally install it because it is a requirement for some package he needs? |
Yes. But the idea is that if you call |
base/pkg/entry.jl
Outdated
end | ||
return resolve() |
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 version isn't right either, as if the checkout fails you should restore the previous state, and not run resolve. likewise if resolve fails after checkout, should roll back.
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.
I should have added a disclaimer that I blindly tried to fix the bug without being familiar with that code at all, so I wouldn't be surprised if that's totally incorrect. I can just note that the tests didn't cover that apparently, and that AFAICT the existing free(pkgs)
method seems to work the same (but maybe I'm missing something). Anyway this commit doesn't need to be kept as removing the whole method also works.
@tkelman Trying to find the simplest fix which would avoid data loss until Pkg3 lands, what kind of solution to do you suggest? |
From last time I looked at this I got to about the same place you did. I think the corruption is due to libgit2 or the windows filesystem not being completely done with the checkout operation before calling the resolve |
So do you think that the PR without the last commit is correct? It doesn't fix #17994 at all, but at least that would turn this question into a design choice (remove or not) rather than into a mix of bug+design. |
It would avoid the corruption at least, but it would also change the error recovery behavior in a way that I don't think is ideal. Is it possible to use 2 nested levels of LibGit2.transact to maybe get both without changing overall recovery behavior if resolve errors? |
Honestly I don't understand the subtleties of that code, but AFAICT we cannot call |
If something wrong with the git operation causes a failure, it should attempt to roll back to the previous state instead of leaving things in whatever in between condition they were at when the error happened. |
But the current code doesn't do that, right? I really don't want to dive into complex improvements of the Pkg system since it's going to be improved, I'm just trying to find the smallest backportable fix to avoid data loss. |
Lines 892 to 899 in 19b3ca7
that's the intent of transact? |
OK, I hadn't noticed the |
Not going to happen at this point. |
The first commit adds a test which is supposed to fail on Windows only. The second commit fixes it.
However, I don't think this solves #17994, since the change just allows the package removal to complete without breaking further
Pkg
calls. We should probably also changePkg.free("X")
to addX
to REQUIRE so that there's no risk of the package being removed byresolve
, since this is what #17994 is about.