提交 f299ebf0 authored 作者: Olivier Delalleau's avatar Olivier Delalleau

Merge

...@@ -12,12 +12,12 @@ def get_lock(): ...@@ -12,12 +12,12 @@ def get_lock():
get_lock.n_lock = 0 get_lock.n_lock = 0
get_lock.lock_dir = os.path.join(compiledir.get_compiledir(), 'lock_dir') get_lock.lock_dir = os.path.join(compiledir.get_compiledir(), 'lock_dir')
if not hasattr(get_lock, 'lock_is_enabled'): if not hasattr(get_lock, 'lock_is_enabled'):
# Currently lock is disabled by default, due to the annoying # Enable lock by default.
# persistence of lock files when compilation is being interrupted. get_lock.lock_is_enabled = True
get_lock.lock_is_enabled = False get_lock.unlocker = Unlocker(get_lock.lock_dir)
# Only really try to acquire the lock if we do not have it already. # Only really try to acquire the lock if we do not have it already.
if get_lock.lock_is_enabled and get_lock.n_lock == 0: if get_lock.lock_is_enabled and get_lock.n_lock == 0:
lock(get_lock.lock_dir, timeout = 60, verbosity = 10) lock(get_lock.lock_dir, timeout = 60, verbosity = 1)
get_lock.n_lock += 1 get_lock.n_lock += 1
def release_lock(): def release_lock():
...@@ -28,7 +28,7 @@ def release_lock(): ...@@ -28,7 +28,7 @@ def release_lock():
assert get_lock.n_lock >= 0 assert get_lock.n_lock >= 0
# Only really release lock once all lock requests have ended. # Only really release lock once all lock requests have ended.
if get_lock.lock_is_enabled and get_lock.n_lock == 0: if get_lock.lock_is_enabled and get_lock.n_lock == 0:
unlock(get_lock.lock_dir) get_lock.unlocker.unlock()
def set_lock_status(use_lock): def set_lock_status(use_lock):
""" """
...@@ -41,7 +41,7 @@ def set_lock_status(use_lock): ...@@ -41,7 +41,7 @@ def set_lock_status(use_lock):
""" """
get_lock.lock_is_enabled = use_lock get_lock.lock_is_enabled = use_lock
def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0): def lock(tmp_dir, timeout=60, min_wait=5, max_wait=10, verbosity=0):
""" """
Obtain lock access by creating a given temporary directory (whose base will Obtain lock access by creating a given temporary directory (whose base will
be created if needed, but will not be deleted after the lock is removed). be created if needed, but will not be deleted after the lock is removed).
...@@ -62,7 +62,7 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0): ...@@ -62,7 +62,7 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0):
@type tmp_dir: string @type tmp_dir: string
@param timeout: time (in seconds) to wait before replacing an existing lock @param timeout: time (in seconds) to wait before replacing an existing lock
@type timeout: int @type timeout: int or None
@param min_wait: minimum time (in seconds) to wait before trying again to @param min_wait: minimum time (in seconds) to wait before trying again to
get the lock get the lock
...@@ -107,7 +107,8 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0): ...@@ -107,7 +107,8 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0):
if last_owner == read_owner: if last_owner == read_owner:
if timeout is not None and time.time() - time_start >= timeout: if timeout is not None and time.time() - time_start >= timeout:
# Timeout exceeded. # Timeout exceeded.
break get_lock.unlocker.unlock()
continue
else: else:
last_owner = read_owner last_owner = read_owner
time_start = time.time() time_start = time.time()
...@@ -148,17 +149,34 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0): ...@@ -148,17 +149,34 @@ def lock(tmp_dir, timeout = 60, min_wait = 5, max_wait = 10, verbosity = 0):
raise raise
continue continue
def unlock(tmp_dir): class Unlocker():
"""
Class wrapper around release mechanism so that the lock is automatically
released when the program exits (even when crashing or being interrupted),
using the __del__ class method.
""" """
Remove current lock.
This function assumes we have obtained the lock using lock(tmp_dir, ...),
so it does not check we are the lock owner.
@param tmp_dir: lock directory that will be removed when releasing the lock def __init__(self, tmp_dir):
@type tmp_dir: string self.tmp_dir = tmp_dir
# Keep a pointer to the 'os' module, otherwise it may not be accessible
# anymore in the __del__ method.
self.os = os
def __del__(self):
self.unlock()
def unlock(self):
""" """
lock_file = os.path.join(tmp_dir, 'lock') Remove current lock.
if os.path.exists(lock_file): This function does not crash if it is unable to properly delete the lock
os.remove(lock_file) file and directory. The reason is that it should be allowed for multiple
if os.path.exists(tmp_dir): jobs running in parallel to unlock the same directory at the same time
os.rmdir(tmp_dir) (e.g. when reaching their timeout limit).
"""
try:
self.os.remove(self.os.path.join(self.tmp_dir, 'lock'))
self.os.rmdir(self.tmp_dir)
except:
# Assume someone else tried to unlock this directory at the same time.
pass
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论