https://github.com/python/cpython/commit/a5fef800d31648d19cecc240a2fa0dc71371753e
commit: a5fef800d31648d19cecc240a2fa0dc71371753e
branch: main
author: Barney Gale <[email protected]>
committer: barneygale <[email protected]>
date: 2024-05-30T03:45:47Z
summary:
GH-89727: Fix FD leak on `os.fwalk()` generator finalization. (#119766)
Follow-up to 3c890b50. Ensure we `os.close()` open file descriptors when
the `os.fwalk()` generator is finalized.
files:
M Lib/os.py
M Lib/test/test_os.py
diff --git a/Lib/os.py b/Lib/os.py
index cef5d90a8c23df..0408e2db79e66e 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -480,8 +480,15 @@ def fwalk(top=".", topdown=True, onerror=None, *,
follow_symlinks=False, dir_fd=
top = fspath(top)
stack = [(_fwalk_walk, (True, dir_fd, top, top, None))]
isbytes = isinstance(top, bytes)
- while stack:
- yield from _fwalk(stack, isbytes, topdown, onerror,
follow_symlinks)
+ try:
+ while stack:
+ yield from _fwalk(stack, isbytes, topdown, onerror,
follow_symlinks)
+ finally:
+ # Close any file descriptors still on the stack.
+ while stack:
+ action, value = stack.pop()
+ if action == _fwalk_close:
+ close(value)
# Each item in the _fwalk() stack is a pair (action, args).
_fwalk_walk = 0 # args: (isroot, dirfd, toppath, topname, entry)
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 7dc5784820e847..de5a86f676c4d5 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -1685,6 +1685,27 @@ def test_fd_leak(self):
self.addCleanup(os.close, newfd)
self.assertEqual(newfd, minfd)
+ @unittest.skipIf(
+ support.is_emscripten, "Cannot dup stdout on Emscripten"
+ )
+ @unittest.skipIf(
+ support.is_android, "dup return value is unpredictable on Android"
+ )
+ def test_fd_finalization(self):
+ # Check that close()ing the fwalk() generator closes FDs
+ def getfd():
+ fd = os.dup(1)
+ os.close(fd)
+ return fd
+ for topdown in (False, True):
+ old_fd = getfd()
+ it = self.fwalk(os_helper.TESTFN, topdown=topdown)
+ self.assertEqual(getfd(), old_fd)
+ next(it)
+ self.assertGreater(getfd(), old_fd)
+ it.close()
+ self.assertEqual(getfd(), old_fd)
+
# fwalk() keeps file descriptors open
test_walk_many_open_files = None
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]