objectstore: manually cleanup tree dir for Object
The tree, which is created by stages and assemblers, might contain immutable files, which for Python 3 currently (version 3.8) leads to errors when the tempfile.TemporaryDirectory is being cleaned up. Therefore, manually cleanup the tree directory, if it exists, via shutil.rmtree with a custom onerror handler that also removes the immutable bit on permission errors.
This commit is contained in:
parent
509d2ee895
commit
04aa5e0aeb
1 changed files with 36 additions and 0 deletions
|
|
@ -3,6 +3,7 @@ import contextlib
|
|||
import errno
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import weakref
|
||||
|
|
@ -52,6 +53,35 @@ def umount(target, lazy=True):
|
|||
subprocess.run(["umount"] + args + [target], check=True)
|
||||
|
||||
|
||||
def remove_tree(path):
|
||||
def fixperms(p):
|
||||
subprocess.run(["chattr", "-i", p],
|
||||
check=False)
|
||||
os.chmod(p, 0o777)
|
||||
|
||||
def unlink(p):
|
||||
try:
|
||||
os.unlink(p)
|
||||
except IsADirectoryError:
|
||||
remove_tree(p)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def on_error(_fn, p, exc_info):
|
||||
e = exc_info[0]
|
||||
if issubclass(e, FileNotFoundError):
|
||||
pass
|
||||
elif issubclass(e, PermissionError):
|
||||
if p != path:
|
||||
fixperms(os.path.dirname(p))
|
||||
fixperms(p)
|
||||
unlink(p)
|
||||
else:
|
||||
raise e
|
||||
|
||||
shutil.rmtree(path, onerror=on_error)
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
class Object:
|
||||
def __init__(self, store: "ObjectStore"):
|
||||
|
|
@ -158,6 +188,12 @@ class Object:
|
|||
def cleanup(self):
|
||||
self._check_readers()
|
||||
self._check_writer()
|
||||
if self._tree:
|
||||
# manually remove the tree, it might contain
|
||||
# files with immutable flag set, which will
|
||||
# throw off standard Python 3 tempdir cleanup
|
||||
remove_tree(self._tree)
|
||||
self._tree = None
|
||||
if self._workdir:
|
||||
self._workdir.cleanup()
|
||||
self._workdir = None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue