Make remove_dir_if_empty a bit more robust against other programs simultaneously deleting the dir or its contents. See #2060340 (Unhandled Exception - FileNotFoundError)

This commit is contained in:
Kovid Goyal 2024-04-07 08:10:30 +05:30
parent b5c688c94d
commit 29dbdcdb69
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -536,16 +536,21 @@ def remove_dir_if_empty(path, ignore_metadata_caches=False):
try: try:
os.rmdir(path) os.rmdir(path)
except OSError as e: except OSError as e:
if e.errno == errno.ENOTEMPTY or len(os.listdir(path)) > 0: try:
entries = os.listdir(path)
except FileNotFoundError: # something deleted path out from under us
return
if e.errno == errno.ENOTEMPTY or len(entries) > 0:
# Some linux systems appear to raise an EPERM instead of an # Some linux systems appear to raise an EPERM instead of an
# ENOTEMPTY, see https://bugs.launchpad.net/bugs/1240797 # ENOTEMPTY, see https://bugs.launchpad.net/bugs/1240797
if ignore_metadata_caches: if ignore_metadata_caches:
try: try:
found = False found = False
for x in os.listdir(path): for x in entries:
if x.lower() in {'.ds_store', 'thumbs.db'}: if x.lower() in {'.ds_store', 'thumbs.db'}:
found = True found = True
x = os.path.join(path, x) x = os.path.join(path, x)
with suppress(FileNotFoundError):
if os.path.isdir(x): if os.path.isdir(x):
import shutil import shutil
shutil.rmtree(x) shutil.rmtree(x)