Skip to content
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

Merged

Conversation

itaisteinherz
Copy link
Contributor

@itaisteinherz itaisteinherz commented Mar 13, 2022

@the-knights-who-say-ni
Copy link

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 Missing

Our records indicate the following people have not signed the CLA:

@itaisteinherz

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
before our records are updated.

You can check yourself to see if the CLA has been received.

Thanks again for the contribution, we look forward to reviewing it!

@itaisteinherz itaisteinherz marked this pull request as ready for review March 13, 2022 21:19
Lib/test/test_os.py Outdated Show resolved Hide resolved
@itaisteinherz
Copy link
Contributor Author

Would be great to have someone take a look at this PR :)

Lib/test/test_os.py Outdated Show resolved Hide resolved
Lib/test/test_os.py Outdated Show resolved Hide resolved
Lib/test/test_os.py Outdated Show resolved Hide resolved
Lib/test/test_os.py Outdated Show resolved Hide resolved
@itaisteinherz itaisteinherz requested a review from zooba March 18, 2022 18:30
proc.terminate()

@support.requires_subprocess()
def test_stat_rmdir_race(self):
Copy link
Contributor

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().

Copy link
Contributor Author

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 handling ERROR_NOT_READY and ERROR_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?)

Copy link
Contributor

@eryksun eryksun Mar 19, 2022

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.

Copy link
Contributor Author

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.

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.

@itaisteinherz
Copy link
Contributor Author

Bump

Copy link
Contributor

@MaxwellDupre MaxwellDupre left a 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.

@zooba
Copy link
Member

zooba commented May 2, 2022

Hopefully that resets the broken status. This looks fine to merge once CI finishes.

@zooba zooba merged commit 39e6b8a into python:main May 2, 2022
@itaisteinherz
Copy link
Contributor Author

@zooba Do I need to manually backport this?

@itaisteinherz itaisteinherz deleted the bugfix/bpo-46785-os-stat-error-handling branch May 3, 2022 05:39
@zooba zooba added needs backport to 3.9 only security fixes needs backport to 3.10 only security fixes labels May 7, 2022
@miss-islington
Copy link
Contributor

Thanks @itaisteinherz for the PR, and @zooba for merging it 🌮🎉.. I'm working now to backport this PR to: 3.10.
🐍🍒⛏🤖

@miss-islington
Copy link
Contributor

Thanks @itaisteinherz for the PR, and @zooba for merging it 🌮🎉.. I'm working now to backport this PR to: 3.9.
🐍🍒⛏🤖 I'm not a witch! I'm not a witch!

@zooba
Copy link
Member

zooba commented May 7, 2022

Let's find out if it needs to be done manually...

@miss-islington
Copy link
Contributor

Sorry, @itaisteinherz and @zooba, I could not cleanly backport this to 3.10 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker 39e6b8ae6a5b49bb23746fdcc354d148ff2d98e3 3.10

@miss-islington
Copy link
Contributor

Sorry @itaisteinherz and @zooba, I had trouble checking out the 3.9 backport branch.
Please backport using cherry_picker on command line.
cherry_picker 39e6b8ae6a5b49bb23746fdcc354d148ff2d98e3 3.9

@zooba
Copy link
Member

zooba commented May 7, 2022

Yeah, looks like it needs to be manual.

itaisteinherz added a commit to itaisteinherz/cpython that referenced this pull request May 9, 2022
…Windows (pythonGH-31858).

(cherry picked from commit 39e6b8a)

Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
@bedevere-bot bedevere-bot removed the needs backport to 3.10 only security fixes label May 9, 2022
@bedevere-bot
Copy link

GH-92577 is a backport of this pull request to the 3.10 branch.

itaisteinherz added a commit to itaisteinherz/cpython that referenced this pull request May 9, 2022
…indows (pythonGH-31858).

(cherry picked from commit 39e6b8a)

Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
@bedevere-bot
Copy link

GH-92578 is a backport of this pull request to the 3.9 branch.

@bedevere-bot bedevere-bot removed the needs backport to 3.9 only security fixes label May 9, 2022
zooba pushed a commit that referenced this pull request May 9, 2022
…GH-31858)

* [3.9] bpo-46785: Fix race condition between os.stat() and unlink on Windows (GH-31858).
(cherry picked from commit 39e6b8a)

Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
zooba pushed a commit that referenced this pull request May 10, 2022
…GH-31858)

* [3.10] bpo-46785: Fix race condition between os.stat() and unlink on Windows (GH-31858).
(cherry picked from commit 39e6b8a)

Co-authored-by: Itai Steinherz <itaisteinherz@gmail.com>
hello-adam pushed a commit to hello-adam/cpython that referenced this pull request Jun 2, 2022
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants