]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39327: Close file descriptors as soon as possible in shutil.rmtree (GH-31384)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 21 Feb 2022 08:07:54 +0000 (00:07 -0800)
committerGitHub <noreply@github.com>
Mon, 21 Feb 2022 08:07:54 +0000 (00:07 -0800)
It fixes the "Text File Busy" OSError when using 'rmtree' on a
windows-managed filesystem in via the VirtualBox shared folder
(and possible other scenarios like a windows-managed network file
system).
(cherry picked from commit b77158b4da449ec5b8f682816a79d004fd65ed07)

Co-authored-by: Lital Natan <litaln@gmail.com>
Lib/shutil.py
Misc/ACKS
Misc/NEWS.d/next/Library/2022-02-17-13-10-50.bpo-39327.ytIT7Z.rst [new file with mode: 0644]

index 752900c58890c98888439075bc4f2bea2e457444..c048cdf9b2cbd53dbc6a72cbe5239c1a15cd04c3 100644 (file)
@@ -656,6 +656,7 @@ def _rmtree_safe_fd(topfd, path, onerror):
         if is_dir:
             try:
                 dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
+                dirfd_closed = False
             except OSError:
                 onerror(os.open, fullname, sys.exc_info())
             else:
@@ -663,6 +664,8 @@ def _rmtree_safe_fd(topfd, path, onerror):
                     if os.path.samestat(orig_st, os.fstat(dirfd)):
                         _rmtree_safe_fd(dirfd, fullname, onerror)
                         try:
+                            os.close(dirfd)
+                            dirfd_closed = True
                             os.rmdir(entry.name, dir_fd=topfd)
                         except OSError:
                             onerror(os.rmdir, fullname, sys.exc_info())
@@ -676,7 +679,8 @@ def _rmtree_safe_fd(topfd, path, onerror):
                         except OSError:
                             onerror(os.path.islink, fullname, sys.exc_info())
                 finally:
-                    os.close(dirfd)
+                    if not dirfd_closed:
+                        os.close(dirfd)
         else:
             try:
                 os.unlink(entry.name, dir_fd=topfd)
@@ -719,6 +723,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
             return
         try:
             fd = os.open(path, os.O_RDONLY)
+            fd_closed = False
         except Exception:
             onerror(os.open, path, sys.exc_info())
             return
@@ -726,6 +731,8 @@ def rmtree(path, ignore_errors=False, onerror=None):
             if os.path.samestat(orig_st, os.fstat(fd)):
                 _rmtree_safe_fd(fd, path, onerror)
                 try:
+                    os.close(fd)
+                    fd_closed = True
                     os.rmdir(path)
                 except OSError:
                     onerror(os.rmdir, path, sys.exc_info())
@@ -736,7 +743,8 @@ def rmtree(path, ignore_errors=False, onerror=None):
                 except OSError:
                     onerror(os.path.islink, path, sys.exc_info())
         finally:
-            os.close(fd)
+            if not fd_closed:
+                os.close(fd)
     else:
         try:
             if _rmtree_islink(path):
index fe7e692e04967df3843075363be7aab1cd48d604..c8d0be6999b78fa8e0356404c2bf5fe2d917f23c 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -418,6 +418,7 @@ Caleb Deveraux
 Catherine Devlin
 Scott Dial
 Alon Diamant
+Lital Natan
 Toby Dickenson
 Mark Dickinson
 Jack Diederich
diff --git a/Misc/NEWS.d/next/Library/2022-02-17-13-10-50.bpo-39327.ytIT7Z.rst b/Misc/NEWS.d/next/Library/2022-02-17-13-10-50.bpo-39327.ytIT7Z.rst
new file mode 100644 (file)
index 0000000..fc6e825
--- /dev/null
@@ -0,0 +1,2 @@
+:func:`shutil.rmtree` can now work with VirtualBox shared  folders when
+running from the guest operating-system.