-
-
Notifications
You must be signed in to change notification settings - Fork 313
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
Fetching multiple times on Windows with gix 0.63.0 eventually results in "Could not move a temporary file into its desired place" #1404
Comments
Thanks for reporting! I expected the current While researching this I noticed that Git does implement retries for renaming tempfiles into place, and maybe, just maybe, the One thing is for sure - if something legitimately opened the index file for reading, nobody is allowed to write over it. Right now I assume nobody really opened it, but the laziness of the filesystem causes files to remain opened even after they have been closed in the same (or another) process. CC @EliahKagan - tempfiles are the greatest issue on Windows and this comment sums up everything I know. Generally I have issues reproducing any of this organically, so I suppose more focussed test-programs have to be created to validate certain changes. |
I just tried the included reproduction from a cold but already initialized project (rebooted from yesterday), I verified that there were no open files, the same thing happens. I also noted that this is reliably reproduced for me by simply running the included example project two times. Any subsequent runs causes the issue to happen. There seems to be something about the state of the git repo which triggers this behavior. I've included a zip file I've also run a diff between the first and the second run in the repo, it seems like when an existing repo is
|
So I've added some file tracing to a branch of gitoxide, this branch in my playground repo uses it. [dependencies.gix]
version = "0.63.0"
features = [
"blocking-http-transport-reqwest",
"blocking-http-transport-reqwest-rust-tls-trust-dns",
"blocking-http-transport-reqwest-native-tls",
"tracing",
]
[patch.crates-io]
gix = { git = "https://github.com/udoprog/gitoxide", branch = "file-tracing" } With this, and tracing_subscriber configured, I get this:
With this we can see that fetching opens the existing index files, which are still open when we try to persist the new temporary files in the same location since they share the same name. This is not an issue on Linux since overwriting the files with new ones won't affect or be blocked by any existing open files. But since Windows uses file locking by default this is what we get. |
I realized that this issue is very likely to be transitory meaning the file I included might not work, since I believe the index files will be different depending on the content of the fetch. So if the remote changes between runs it might succeed. |
Thanks for researching this and providing everything one would need for a reproduction. Something I confused initially is that when you write However, with packs and indices, this is different as they will be held open once the index (and later its pack) have been lazily loaded. Once a fetch is repeated the same file is received, which it then tries to move into place. What's great is that in this case, we could ignore these errors entirely (if the file destination existed, at least), as it's clear that thanks to the hash in the name, the new file must have the same content as the old one. Of course, there is an issue before that which is that it should notice that there is nothing to do. Thanks to On the wire, fix
and for
So Git does the same, but does not fail. The reason for this probably is that it receives an empty pack.
interestingly,
So the solution should be to discard empty packs, as indeed, otherwise it should never receive a pack that it already has. But even if it does, it should be save to still use the assumption that an existing pack is the same as the one that would be put in place. |
Failure can occour on Windows as it's likely such a pack or index is already opened during negotiation. Then, when an empty fetch via `--depth 1` is repeated, a temporary file would be renamed onto one an mmapped pack or index, causing a failure. Now packs or indices aren't written anymore if they are empty.
Failure can occour on Windows as it's likely such a pack or index is already opened during negotiation. Then, when an empty fetch via `--depth 1` is repeated, a temporary file would be renamed onto one an mmapped pack or index, causing a failure. Now packs or indices aren't written anymore if they are empty.
Failure can occour on Windows as it's likely such a pack or index is already opened during negotiation. Then, when an empty fetch via `--depth 1` is repeated, a temporary file would be renamed onto one an mmapped pack or index, causing a failure. Now packs or indices aren't written anymore if they are empty.
Hi! I'm sorry to report that I'm still seeing this, but only when using I've updated the reproduction branch: https://github.com/udoprog/playground/tree/gix-issue In order to reproduce, you have to delete the original repository used for testing. Since it seems like if you sync once with This is my full test session:
|
Thanks for retesting this! The core issue was that during negotiation, it would access packed objects, leaving the respective packs memory mapped. Then, when receiving a pack that is one that it already has, it fails. Pulling exactly the same pack should not happen, but it seems it more likely with The solution will be to not fail if the target file already exists as we know it has the right content thanks to the hash in its filename. Another option could be to mmap files such that Windows allows them to be replaced, but I think I will take the tempfile route for now. |
…nes (#1404). That way, on Windows there is no chance for access-denied errors. Maybe there are other advantages as well even for Unix. Since packs are usually written rarely, in comparison to loose objects, the extra file accesss seems acceptable.
…nes (#1404). That way, on Windows there is no chance for access-denied errors. Maybe there are other advantages as well even for Unix. Since packs are usually written rarely, in comparison to loose objects, the extra file accesss seems acceptable.
Current behavior 😯
I have a project that uses gix to try to fetch from a remote repo, it results in an error I'm either not sure how to deal with or if it's a bug.
After running the provided example project a few times (2-3), I get this output:
Steps to reproduce 🕹
The gix dependency is configured like this to use reqwest:
I've set up a minimal project here which tries to fetch
refs/tags/v4
fromactions/upload-artifact
:https://github.com/udoprog/playground/tree/gix-issue
The text was updated successfully, but these errors were encountered: