-
-
Notifications
You must be signed in to change notification settings - Fork 31k
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
bpo-46785: Fix race condition between os.stat()
and unlink
#31858
bpo-46785: Fix race condition between os.stat()
and unlink
#31858
Conversation
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept this contribution by verifying everyone involved has signed the PSF contributor agreement (CLA). CLA MissingOur records indicate the following people have not signed the CLA: For legal reasons we need all the people listed to sign the CLA before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. If you have recently signed the CLA, please wait at least one business day You can check yourself to see if the CLA has been received. Thanks again for the contribution, we look forward to reviewing it! |
Would be great to have someone take a look at this PR :) |
Lib/test/test_os.py
Outdated
proc.terminate() | ||
|
||
@support.requires_subprocess() | ||
def test_stat_rmdir_race(self): |
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 don't think another test of FileNotFoundError
is needed. Maybe there could be a test for the ERROR_NOT_READY
case due to media removal, but I don't see how to set that up with the tools at hand, and it's so rare that it's not a practical problem. The far more likely case is that CreateFileW()
fails with ERROR_NOT_READY
, which isn't handled in os.stat()
.
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.
- Regarding the test - why not? I don't like the code duplication, but the test isn't too complicated, and will verify in the future that no regressions occur.
- Regarding
ERROR_NOT_READY
not being handled - I didn't notice that. It seems to me like handlingERROR_NOT_READY
andERROR_BAD_NET_NAME
in this PR doesn't make much sense then, and should be done (and tested manually/programmatically) in another PR. (By the way, is there an issue in the issue tracker for this?)
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.
The ERROR_PATH_NOT_FOUND
case is basically the same condition as ERROR_FILE_NOT_FOUND
. When CreateFileW()
is called, the file and its parent directory still exist, but by the time FindFirstFileW()
is called, one or both is gone. I can't see anyone ever modifying the os.stat()
implementation to remove handling of one error but not the other. These two errors are the far more likely cases, e.g. some other thread is removing the tree with something like shutil.rmtree()
.
ERROR_PATH_NOT_FOUND
would also occur if a removable drive gets removed with freakish coincidental timing. That's basically the same case as ERROR_BAD_NETNAME
(share removed) and ERROR_NOT_READY
(removable media removed). These are all very unlikely in practice, but they're possible, and they fall into the same general category of the file no longer exists. Returning a PermissionError
for ERROR_ACCESS_DENIED
(5) or ERROR_SHARING_VIOLATION
(32) for a file that no longer exists is pointless. It's hard to test these cases, but that doesn't mean they should be excluded from the PR entirely.
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.
The
ERROR_PATH_NOT_FOUND
case is basically the same condition asERROR_FILE_NOT_FOUND
.
I don't disagree. I'll remove the test.
It's hard to test these cases, but that doesn't mean they should be excluded from the PR entirely.
I'm fine with including them, but I also wanted to make sure that there's an issue for the more general case you mentioned.
Bump |
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.
Ran 316 tests in 6.177s
OK (skipped=47)
Looks ok.
Hopefully that resets the broken status. This looks fine to merge once CI finishes. |
@zooba Do I need to manually backport this? |
Thanks @itaisteinherz for the PR, and @zooba for merging it 🌮🎉.. I'm working now to backport this PR to: 3.10. |
Thanks @itaisteinherz for the PR, and @zooba for merging it 🌮🎉.. I'm working now to backport this PR to: 3.9. |
Let's find out if it needs to be done manually... |
Sorry, @itaisteinherz and @zooba, I could not cleanly backport this to |
Sorry @itaisteinherz and @zooba, I had trouble checking out the |
Yeah, looks like it needs to be manual. |
…Windows (pythonGH-31858). (cherry picked from commit 39e6b8a) Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
GH-92577 is a backport of this pull request to the 3.10 branch. |
…indows (pythonGH-31858). (cherry picked from commit 39e6b8a) Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
GH-92578 is a backport of this pull request to the 3.9 branch. |
…pythonGH-31858) * [3.9] bpo-46785: Fix race condition between os.stat() and unlink on Windows (pythonGH-31858). (cherry picked from commit 39e6b8a) Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
https://bugs.python.org/issue46785