-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
poetry add/update/install can fail on Windows during temp directory cleanup #1031
Comments
The |
First, I should state that the example I presented in the issue was copy pasted is not my actual pull request. It was just an example thrown up for discussion. You should reference my pull request if we're talking about the technical details of the implementation. This isn't actually an error though, and is a fundamental method of dealing with directory deletion in Windows. So outputting an error doesn't make sense. At most it would be a debug message. I would point out though, that this is 6 seconds until catastrophic failure. If you reach the 6 seconds you will have poetry crash with an error. So it's not like it's just a slow command, it's a slow command followed by a crash which is noticeably more acceptable in practice. Further, I don't actually know how to output a message from this function in a way that is consistent with poetry, But it's not like there aren't other long running commands that provide very little feedback during their execution (creating a virtual environment is one of these) The pull request is 3 attempts at 2 seconds each, but this is up for discussion. I do not know how much time is needed to get a near guarantee of directory deletion on Windows, but there is a decent chance we can run it for only 3 attempts at 1 second per. I want to stress though. This fix or something along these lines is a requirement to claim that Poetry supports Windows, as currently in certain situations and setups it will just flat out fail as a result of this problem. Side note: I updated the pull request to match coding standards. It was such a simple change I thought I surely couldn't mess it up. But nope: Two spaces before in-line comments... |
Would you like to use this method to find out which program kept the files? P.S If this issue keeps you from trying poetry, it will keeps you from trying poetry forever. |
I don't think you recognize the problem here. When you mark a file for deletion in Windows, it does not delete immediately. It is held in stasis until all references to the file clear, and then at some arbitrary point in the future it is removed.
As a result, it will error when it tries to delete the parent directory while the files within it are waiting on removal. These will be removed very quickly, within seconds, generally less than 1 second, but this errors regardless. This is a well known problem with Windows. Many other projects have faced this issue and implement a delayed deletion to deal with it. There is a reason that Poetry gives There is no sensible way for me to use Unlocker to determine what is holding it open for the 100ms it's grabbed for. It could simply be the Windows file system! This is a Windows issue. It is unrelated to my PC in particular, but the windows ecosystem on a whole. The speed of your system can be enough to make something succeed or fail. The speed of your HDD makes a difference. There is no sensible way to force or test for this, you just must know that the problem exists and deal with it. |
But my point seems not that odd: https://stackoverflow.com/questions/24699854/strange-error-when-deleting-directory-from-java-0-bytes-access-denied You made me search file descriptors without context in |
Just to be clear. This is not a problem involving a regular program actually locking a file open for some reason. It is the result of a program responding to a change notification (specifically, the delete notification) This is basically like having a callback in code: def on_delete(file):
# Do some stuff
print(f"Do some stuff with {file.name}") That file is in the process of being deleted. Poetry then fails from trying to delete the parent directory before this occurs. Python was told "yep, that file will be deleted.... at some point", but poetry assumes that means "right now", which means when it tires to remove the parent directory the file is not yet gone and we get the error. The file is removed mere seconds later, but by then it's too late. Poetry has crashed. So that's why you need a retry loop. Either that or you catch the failure, ignore the error, and cleanup tmp files at a later time (because Windows doesn't do that). Either way, something has to be done here to support this weird quirk of Windows. |
@Pluckerpluck Your example made this a serious issue absolutely. What's the evidence of the robustness about |
And has been in both of those codebases for over 5 years. As a "recent" example, Similar code is also included in cpython itself! In particular, while they have agreed to not include this into base Python, they do still need it for their own Windows tests. Note: They wait for less than 1 second though, starting at 0.001 seconds and increasing exponentially up to a maximum of 1. So maybe the initial wait of 2 seconds it needlessly large, however given that this is running during With regards to testing, we used to have a single PC that consistently failed due to this error, and this change means that the system now installs requirements properly. We now have been using this fix for some time and have yet to run into any issues. The problem is more of an issue with Windows buildbots though, where you can't just "retry" the install in the same way you would on a PC. |
Please minimize the interval and the required runs of the loop. The name of the function had better be |
Do you agree it's good to use the same system as CPython? Start at 1ms wait, and exponentially scale to 1 second wait (this means the total possible wait is < 2 seconds). If Python themselves do it, then it must be reasonable. I don't understand the issue with the name |
If it works with your method for that reason (always), it will only need to run twice exactly. |
There is no guarantee it will need only two runs! Python themselves run the check up to 10 times. This is what CPython does:
This results in a maximum wait of 1 second, but a minimum wait of 1ms. The idea being that you will avoid the Windows issue in the least amount of time needed. I suggest we implement the system that Python themselves use. There is probably a good reason they choose to do it that way. Checking only twice means we have to catch the worst case, which means waiting for 1 second every time. While rare that's just a waste of time for no good reason. Again. Why can't this be called |
For reference: Associated bug ticket: https://bugs.python.org/issue15496 - commit referencing it: python/cpython@6f5c5cb (via Blame feature on GitHub) |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This bug still happens, however it looks like #1032 is abandoned. |
Still happens in Poetry 1.1.5, why was #1032 not merged? Poetry is almost unusable because my This also appears to be related to #1612 (comment) Versions:
Note that in the output below, I replaced some paths with their equivalent environment variables (%userprofile%, etc) Example demonstrating issue from fresh environment
|
It wasn't merged becuase I happend to stop using poetry (it was for work originally) and never got around to adding the tests required to merge the pull request. I'll tell you what. I'll try to clean it up and update the pull request over this weekend. No promises though. I literally don't use poetry anymore... Note: You can manually apply this patch yourself to Poetry if you want it. Edit: Yep... ended up doing nothing. Mostly becuase I completley forgot about this.... |
Any news about this issue? I'm still having same problem... |
When deleting temporary directories on Windows try a few times so we get around a Windows error, see issue python-poetry#1031 for more details.
The PR python-poetry/poetry-core#460 recreates the patch that should address the issue. It looks to be a fairly widespread problem with poetry on windows and fails about 10% of our CI builds. |
@python-poetry/triage |
It is 2023. I just switched to
Any suggestions? |
Hey .. I can understand that you are frustraded.. but there is a gold rule in all projects in the entire world .. be kind! |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
If something goes wrong during an installation, a file is often held open for just a little too long for
TemporaryDirectory
causing it to error out with errors such as:This is an incredibly unhelpful error and masks all sorts of other problems.
It is causes by a bug in
shutil.rmtree
which can fail on Windows from time to time. It can fail for a variety of reasons, but very commonly it's simply a process holding the file active for just a little too long resulting inos.rmdir
failing. This is despite the directory actually being empty when you check (i.e. it's just slow).This is a known error in Python, of which there is no plan to fix: https://bugs.python.org/issue29982
As a result, I suggest the avoidance of using
TemporaryDirectory
, over which we have no control of the cleanup, and instead usemkdtemp
manually, followed by a short loop to try and remove the directory.In particular in
helpers.py
:should instead be something like:
This is done in a few other projects:
The latter is where I ripped the example function.
I'm willing to write a pull request later to test this myself. But I'm writing the issue now as it is a problem that should be dealt with.
The text was updated successfully, but these errors were encountered: