mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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).
This commit is contained in:
parent
a3fcca4af1
commit
b77158b4da
3 changed files with 13 additions and 2 deletions
|
@ -648,6 +648,7 @@ def _rmtree_safe_fd(topfd, path, onerror):
|
||||||
if is_dir:
|
if is_dir:
|
||||||
try:
|
try:
|
||||||
dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
|
dirfd = os.open(entry.name, os.O_RDONLY, dir_fd=topfd)
|
||||||
|
dirfd_closed = False
|
||||||
except OSError:
|
except OSError:
|
||||||
onerror(os.open, fullname, sys.exc_info())
|
onerror(os.open, fullname, sys.exc_info())
|
||||||
else:
|
else:
|
||||||
|
@ -655,6 +656,8 @@ def _rmtree_safe_fd(topfd, path, onerror):
|
||||||
if os.path.samestat(orig_st, os.fstat(dirfd)):
|
if os.path.samestat(orig_st, os.fstat(dirfd)):
|
||||||
_rmtree_safe_fd(dirfd, fullname, onerror)
|
_rmtree_safe_fd(dirfd, fullname, onerror)
|
||||||
try:
|
try:
|
||||||
|
os.close(dirfd)
|
||||||
|
dirfd_closed = True
|
||||||
os.rmdir(entry.name, dir_fd=topfd)
|
os.rmdir(entry.name, dir_fd=topfd)
|
||||||
except OSError:
|
except OSError:
|
||||||
onerror(os.rmdir, fullname, sys.exc_info())
|
onerror(os.rmdir, fullname, sys.exc_info())
|
||||||
|
@ -668,7 +671,8 @@ def _rmtree_safe_fd(topfd, path, onerror):
|
||||||
except OSError:
|
except OSError:
|
||||||
onerror(os.path.islink, fullname, sys.exc_info())
|
onerror(os.path.islink, fullname, sys.exc_info())
|
||||||
finally:
|
finally:
|
||||||
os.close(dirfd)
|
if not dirfd_closed:
|
||||||
|
os.close(dirfd)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
os.unlink(entry.name, dir_fd=topfd)
|
os.unlink(entry.name, dir_fd=topfd)
|
||||||
|
@ -711,6 +715,7 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
fd = os.open(path, os.O_RDONLY)
|
fd = os.open(path, os.O_RDONLY)
|
||||||
|
fd_closed = False
|
||||||
except Exception:
|
except Exception:
|
||||||
onerror(os.open, path, sys.exc_info())
|
onerror(os.open, path, sys.exc_info())
|
||||||
return
|
return
|
||||||
|
@ -718,6 +723,8 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
||||||
if os.path.samestat(orig_st, os.fstat(fd)):
|
if os.path.samestat(orig_st, os.fstat(fd)):
|
||||||
_rmtree_safe_fd(fd, path, onerror)
|
_rmtree_safe_fd(fd, path, onerror)
|
||||||
try:
|
try:
|
||||||
|
os.close(fd)
|
||||||
|
fd_closed = True
|
||||||
os.rmdir(path)
|
os.rmdir(path)
|
||||||
except OSError:
|
except OSError:
|
||||||
onerror(os.rmdir, path, sys.exc_info())
|
onerror(os.rmdir, path, sys.exc_info())
|
||||||
|
@ -728,7 +735,8 @@ def rmtree(path, ignore_errors=False, onerror=None):
|
||||||
except OSError:
|
except OSError:
|
||||||
onerror(os.path.islink, path, sys.exc_info())
|
onerror(os.path.islink, path, sys.exc_info())
|
||||||
finally:
|
finally:
|
||||||
os.close(fd)
|
if not fd_closed:
|
||||||
|
os.close(fd)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if _rmtree_islink(path):
|
if _rmtree_islink(path):
|
||||||
|
|
|
@ -429,6 +429,7 @@ Caleb Deveraux
|
||||||
Catherine Devlin
|
Catherine Devlin
|
||||||
Scott Dial
|
Scott Dial
|
||||||
Alon Diamant
|
Alon Diamant
|
||||||
|
Lital Natan
|
||||||
Toby Dickenson
|
Toby Dickenson
|
||||||
Mark Dickinson
|
Mark Dickinson
|
||||||
Jack Diederich
|
Jack Diederich
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
:func:`shutil.rmtree` can now work with VirtualBox shared folders when
|
||||||
|
running from the guest operating-system.
|
Loading…
Add table
Add a link
Reference in a new issue