]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-79325: Fix recursion error in TemporaryDirectory cleanup on Windows (GH...
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 7 Dec 2023 17:46:30 +0000 (19:46 +0200)
committerGitHub <noreply@github.com>
Thu, 7 Dec 2023 17:46:30 +0000 (17:46 +0000)
(cherry picked from commit b2923a61a10dc2717f4662b590cc9f6d181c6983)

Lib/tempfile.py
Lib/test/test_tempfile.py
Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst [new file with mode: 0644]

index f59a63a7b45b3622a8442ca911bdb123664f7f83..abb5f45103f459134f6283866bf3c441781e2f75 100644 (file)
@@ -876,9 +876,14 @@ class TemporaryDirectory:
             ignore_errors=self._ignore_cleanup_errors)
 
     @classmethod
-    def _rmtree(cls, name, ignore_errors=False):
+    def _rmtree(cls, name, ignore_errors=False, repeated=False):
         def onerror(func, path, exc_info):
             if issubclass(exc_info[0], PermissionError):
+                if repeated and path == name:
+                    if ignore_errors:
+                        return
+                    raise
+
                 try:
                     if path != name:
                         _resetperms(_os.path.dirname(path))
@@ -911,7 +916,8 @@ class TemporaryDirectory:
                             if ignore_errors:
                                 return
                             raise
-                        cls._rmtree(path, ignore_errors=ignore_errors)
+                        cls._rmtree(path, ignore_errors=ignore_errors,
+                                    repeated=(path == name))
                 except FileNotFoundError:
                     pass
             elif issubclass(exc_info[0], FileNotFoundError):
index 675edc8de9cca55a390ab39a187dd4cd8c097c4c..e735a2520e77eeb3f084ba67ad3e7dc9beaa6a00 100644 (file)
@@ -1543,6 +1543,17 @@ class TestTemporaryDirectory(BaseTestCase):
                 with self.assertRaises(PermissionError):
                     temp_dir.cleanup()
 
+    @unittest.skipUnless(os.name == "nt", "Only on Windows.")
+    def test_cleanup_with_used_directory(self):
+        with tempfile.TemporaryDirectory() as working_dir:
+            temp_dir = self.do_create(dir=working_dir)
+            subdir = os.path.join(temp_dir.name, "subdir")
+            os.mkdir(subdir)
+            with os_helper.change_cwd(subdir):
+                # Previously raised RecursionError on some OSes
+                # (e.g. Windows). See bpo-35144.
+                with self.assertRaises(PermissionError):
+                    temp_dir.cleanup()
 
     @os_helper.skip_unless_symlink
     def test_cleanup_with_symlink_to_a_directory(self):
diff --git a/Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst b/Misc/NEWS.d/next/Library/2023-12-05-18-57-53.gh-issue-79325.P2vMVK.rst
new file mode 100644 (file)
index 0000000..f3c32d2
--- /dev/null
@@ -0,0 +1,2 @@
+Fix an infinite recursion error in :func:`tempfile.TemporaryDirectory`
+cleanup on Windows.