Skip to content

Commit 959846b

Browse files
bpo-39327: Close file descriptors as soon as possible in shutil.rmtree (GH-31384)
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 b77158b) Co-authored-by: Lital Natan <[email protected]>
1 parent e7115d5 commit 959846b

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

Lib/shutil.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -656,13 +656,16 @@ def _rmtree_safe_fd(topfd, path, onerror):
656656
if is_dir:
657657
try:
658658
dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
659+
dirfd_closed = False
659660
except OSError:
660661
onerror(os.open, fullname, sys.exc_info())
661662
else:
662663
try:
663664
if os.path.samestat(orig_st, os.fstat(dirfd)):
664665
_rmtree_safe_fd(dirfd, fullname, onerror)
665666
try:
667+
os.close(dirfd)
668+
dirfd_closed = True
666669
os.rmdir(entry.name, dir_fd=topfd)
667670
except OSError:
668671
onerror(os.rmdir, fullname, sys.exc_info())
@@ -676,7 +679,8 @@ def _rmtree_safe_fd(topfd, path, onerror):
676679
except OSError:
677680
onerror(os.path.islink, fullname, sys.exc_info())
678681
finally:
679-
os.close(dirfd)
682+
if not dirfd_closed:
683+
os.close(dirfd)
680684
else:
681685
try:
682686
os.unlink(entry.name, dir_fd=topfd)
@@ -719,13 +723,16 @@ def onerror(*args):
719723
return
720724
try:
721725
fd = os.open(path, os.O_RDONLY)
726+
fd_closed = False
722727
except Exception:
723728
onerror(os.open, path, sys.exc_info())
724729
return
725730
try:
726731
if os.path.samestat(orig_st, os.fstat(fd)):
727732
_rmtree_safe_fd(fd, path, onerror)
728733
try:
734+
os.close(fd)
735+
fd_closed = True
729736
os.rmdir(path)
730737
except OSError:
731738
onerror(os.rmdir, path, sys.exc_info())
@@ -736,7 +743,8 @@ def onerror(*args):
736743
except OSError:
737744
onerror(os.path.islink, path, sys.exc_info())
738745
finally:
739-
os.close(fd)
746+
if not fd_closed:
747+
os.close(fd)
740748
else:
741749
try:
742750
if _rmtree_islink(path):

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ Caleb Deveraux
418418
Catherine Devlin
419419
Scott Dial
420420
Alon Diamant
421+
Lital Natan
421422
Toby Dickenson
422423
Mark Dickinson
423424
Jack Diederich
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`shutil.rmtree` can now work with VirtualBox shared folders when
2+
running from the guest operating-system.

0 commit comments

Comments
 (0)