mirror of
https://github.com/clearml/clearml-agent
synced 2025-02-12 07:38:04 +00:00
Fix IOError on file lock when using shared folder
This commit is contained in:
parent
09c5ef99af
commit
74edf6aa36
@ -32,7 +32,7 @@ def open_atomic(filename, binary=True):
|
|||||||
... os.remove(filename)
|
... os.remove(filename)
|
||||||
|
|
||||||
>>> with open_atomic(filename) as fh:
|
>>> with open_atomic(filename) as fh:
|
||||||
... written = fh.write(b'test')
|
... written = fh.write(b"test")
|
||||||
>>> assert os.path.exists(filename)
|
>>> assert os.path.exists(filename)
|
||||||
>>> os.remove(filename)
|
>>> os.remove(filename)
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ class FileLock(object):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self, filename, mode='a', timeout=DEFAULT_TIMEOUT,
|
self, filename, mode='a', timeout=DEFAULT_TIMEOUT,
|
||||||
check_interval=DEFAULT_CHECK_INTERVAL, fail_when_locked=False,
|
check_interval=DEFAULT_CHECK_INTERVAL, fail_when_locked=False,
|
||||||
flags=LOCK_METHOD, **file_open_kwargs):
|
**file_open_kwargs):
|
||||||
"""Lock manager with build-in timeout
|
"""Lock manager with build-in timeout
|
||||||
|
|
||||||
filename -- filename
|
filename -- filename
|
||||||
@ -101,11 +101,12 @@ class FileLock(object):
|
|||||||
self.timeout = timeout
|
self.timeout = timeout
|
||||||
self.check_interval = check_interval
|
self.check_interval = check_interval
|
||||||
self.fail_when_locked = fail_when_locked
|
self.fail_when_locked = fail_when_locked
|
||||||
self.flags = flags
|
self.flags_read = constants.LOCK_SH | constants.LOCK_NB
|
||||||
|
self.flags_write = constants.LOCK_EX | constants.LOCK_NB
|
||||||
self.file_open_kwargs = file_open_kwargs
|
self.file_open_kwargs = file_open_kwargs
|
||||||
|
|
||||||
def acquire(
|
def acquire(
|
||||||
self, timeout=None, check_interval=None, fail_when_locked=None):
|
self, timeout=None, check_interval=None, fail_when_locked=None, readonly=False):
|
||||||
"""Acquire the locked filehandle"""
|
"""Acquire the locked filehandle"""
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.timeout
|
timeout = self.timeout
|
||||||
@ -123,12 +124,13 @@ class FileLock(object):
|
|||||||
if fh:
|
if fh:
|
||||||
return fh
|
return fh
|
||||||
|
|
||||||
# Get a new filehandler
|
_fh = None
|
||||||
fh = self._get_fh()
|
|
||||||
try:
|
try:
|
||||||
|
# Get a new filehandler
|
||||||
|
_fh = self._get_fh()
|
||||||
# Try to lock
|
# Try to lock
|
||||||
fh = self._get_lock(fh)
|
fh = self._get_lock(_fh, readonly=readonly)
|
||||||
except exceptions.LockException as exception:
|
except (exceptions.LockException, IOError) as exception:
|
||||||
# Try till the timeout has passed
|
# Try till the timeout has passed
|
||||||
timeoutend = current_time() + timeout
|
timeoutend = current_time() + timeout
|
||||||
while timeoutend > current_time():
|
while timeoutend > current_time():
|
||||||
@ -144,16 +146,18 @@ class FileLock(object):
|
|||||||
raise exceptions.AlreadyLocked(exception)
|
raise exceptions.AlreadyLocked(exception)
|
||||||
|
|
||||||
else: # pragma: no cover
|
else: # pragma: no cover
|
||||||
|
if not _fh:
|
||||||
|
_fh = self._get_fh()
|
||||||
# We've got the lock
|
# We've got the lock
|
||||||
fh = self._get_lock(fh)
|
fh = self._get_lock(_fh, readonly=readonly)
|
||||||
break
|
break
|
||||||
|
|
||||||
except exceptions.LockException:
|
except (exceptions.LockException, IOError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# We got a timeout... reraising
|
# We got a timeout... reraising
|
||||||
raise exceptions.LockException(exception)
|
raise exceptions.LockTimeout(exception)
|
||||||
|
|
||||||
# Prepare the filehandle (truncate if needed)
|
# Prepare the filehandle (truncate if needed)
|
||||||
fh = self._prepare_fh(fh)
|
fh = self._prepare_fh(fh)
|
||||||
@ -176,16 +180,37 @@ class FileLock(object):
|
|||||||
pass
|
pass
|
||||||
self.fh = None
|
self.fh = None
|
||||||
|
|
||||||
|
def delete_lock_file(self):
|
||||||
|
# type: () -> bool
|
||||||
|
"""
|
||||||
|
Remove the local file used for locking (fail if file is locked)
|
||||||
|
|
||||||
|
:return: True is successful
|
||||||
|
"""
|
||||||
|
if self.fh:
|
||||||
|
return False
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
os.unlink(path=self.filename)
|
||||||
|
except BaseException:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def _get_fh(self):
|
def _get_fh(self):
|
||||||
"""Get a new filehandle"""
|
"""Get a new filehandle"""
|
||||||
|
# Create the parent directory if it doesn't exist
|
||||||
|
path, name = os.path.split(self.filename)
|
||||||
|
if path and not os.path.isdir(path): # pragma: no cover
|
||||||
|
os.makedirs(path, exist_ok=True)
|
||||||
|
|
||||||
return open(self.filename, self.mode, **self.file_open_kwargs)
|
return open(self.filename, self.mode, **self.file_open_kwargs)
|
||||||
|
|
||||||
def _get_lock(self, fh):
|
def _get_lock(self, fh, readonly=False):
|
||||||
"""
|
"""
|
||||||
Try to lock the given filehandle
|
Try to lock the given filehandle
|
||||||
|
|
||||||
returns LockException if it fails"""
|
returns LockException if it fails"""
|
||||||
lock(fh, self.flags)
|
lock(fh, self.flags_read if readonly else self.flags_write)
|
||||||
return fh
|
return fh
|
||||||
|
|
||||||
def _prepare_fh(self, fh):
|
def _prepare_fh(self, fh):
|
||||||
|
Loading…
Reference in New Issue
Block a user