Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-89727: Fix os.fwalk RecursionError on deep trees#100347
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
jonburdo commented Dec 19, 2022 • edited by bedevere-bot
Loading Uh oh!
There was an error while loading. Please reload this page.
edited by bedevere-bot
Uh oh!
There was an error while loading. Please reload this page.
bedevere-bot commented Dec 19, 2022
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
bedevere-bot commented Dec 19, 2022
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
jonburdo commented Dec 19, 2022 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
TODO:
|
Uh oh!
There was an error while loading. Please reload this page.
Use a stack to implement os.walk iteratively instead of recursively to avoid hitting recursion limits on deeply nested trees.
…2015) Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Christian Heimes <christian@python.org> Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com> Fixespython#89051
…ions in imaplib docs (python#99625)
…with `_read_ready_cb` (python#100349)
Make sure file descriptors get closed if an exception occurs right after the file descriptor was popped from the stack. Also catch exceptions thrown by calling os.close on an already-closed file-descriptor when doing file descriptor cleanup.
jonburdo commented Mar 23, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
Note that handling of a single exception should function the same, but repeated errors will interrupt the file descriptor cleanup (closing). Imagine a user holds down try: ... except: forfdinreversed(fd_stack): try: close(fd) exceptOSError: passraiseI'm not sure this is a problem. If I understand correctly, neither versions handles this perfectly. It seemed worth mentioning though. I thought about changing the |
jonburdo commented Mar 24, 2023
Opening this up for review in response to #89727 (comment) |
Uh oh!
There was an error while loading. Please reload this page.
If an exception occurred between `close(fd_stack[-1])` and `fd_stack.pop()`, then we would close the fd a second time in the except clause. It would be better to risk leaving the fd open, as the previous implementation of fwalk could
barneygale left a comment
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.
LGTM, nice work!
barneygale commented Mar 31, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
A thought: could you merge |
Lib/os.py Outdated
| except: | ||
| foraction, valueinreversed(stack): | ||
| ifactionis_WalkAction.CLOSE: | ||
| try: | ||
| close(value) | ||
| exceptOSError: | ||
| pass | ||
| raise |
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.
Could this be a finally: block?
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.
Sure, would you consider that more readable or explicit? I just didn't see any benefit, since this is only needed if an exception occurs. The only functional difference would be that we'd iterate over an empty list if no exceptions occur right?
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 think I'd consider it more explicit, though feel free to wait for another opinion if you'd like.
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'd also prefer finally here. Not sure if it actually delivers any functional benefit here (can't remember the exact semantics off the top of my head...), but it does feel at least more readable to me.
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.
Makes sense, thanks for clarifying. I'll change it to finally. Functionally, I think finally is slightly worse but it's negligible.
In this case, changing to finally is functionally equivalent to adding an else clause with the same for-loop:
try: ... except: foraction, valueinreversed(stack): ... raiseelse: foraction, valueinreversed(stack): ...If no exception occurs in the try, then stack will be empty and all of the fds will have been closed already. So changing to finally means we're adding a step where we simply iterate over an empty list - unnecessary, but costs almost nothing.
To me, a bare except indicates a cleanup step, but finally is even more explicit, so it probably makes sense here.
barneygale commented Jun 1, 2024
@jonburdo I've fixed this in another PR - #119638. Shamefully I forgot about this PR :(. Comparing our code, I think we arrived at similar solutions, the main difference being that I moved the |
jonburdo commented Jun 2, 2024
@barneygale No worries! Thanks for mentioning it. I meant to follow up on this. I'll take a look at your PR. Thanks for working on this function and the related ones! It feels great to see these improvements :) |
Use a stack to implement os.fwalk iteratively instead of recursively to avoid hitting recursion limits on deeply nested trees.
Similar to how this is done for
os.walkin #99803