Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.2k
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 ourterms of service andprivacy 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
bedevere-bot commentedDec 19, 2022
Most changes to Pythonrequire a NEWS entry. Please add it using theblurb_it web app or theblurb command-line tool. |
bedevere-bot commentedDec 19, 2022
Most changes to Pythonrequire a NEWS entry. Please add it using theblurb_it web app or theblurb command-line tool. |
jonburdo commentedDec 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 toavoid 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 commentedMar 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:passraise I'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 |
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
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 commentedMar 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: | ||
for action, value in reversed(stack): | ||
if action is _WalkAction.CLOSE: | ||
try: | ||
close(value) | ||
except OSError: | ||
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 afinally:
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 preferfinally
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 tofinally
. Functionally, I thinkfinally
is slightly worse but it's negligible.
In this case, changing tofinally
is functionally equivalent to adding anelse
clause with the same for-loop:
try: ...except:foraction,valueinreversed(stack): ...raiseelse:foraction,valueinreversed(stack): ...
If no exception occurs in thetry
, thenstack
will be empty and all of the fds will have been closed already. So changing tofinally
means we're adding a step where we simply iterate over an empty list - unnecessary, but costs almost nothing.
To me, a bareexcept
indicates a cleanup step, butfinally
is even more explicit, so it probably makes sense here.
@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 |
@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 :) |
Uh oh!
There was an error while loading.Please reload this page.
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.walk
in#99803