def lockfile(name, shared=False, retry=True):
"""
Use the file fn as a lock file, return when the lock has been acquired.
Returns a variable to pass to unlockfile().
"""
config.logger.debug("take lockfile %s", name)
dirname = os.path.dirname(name)
mkdirhier(dirname)
if not os.access(dirname, os.W_OK):
logger.error("Unable to acquire lock '%s', directory is not writable",
name)
sys.exit(1)
operation = fcntl.LOCK_EX
if shared:
operation = fcntl.LOCK_SH
if not retry:
operation = operation | fcntl.LOCK_NB
while True:
# If we leave the lockfiles lying around there is no problem
# but we should clean up after ourselves. This gives potential
# for races though. To work around this, when we acquire the lock
# we check the file we locked was still the lock file on disk.
# by comparing inode numbers. If they don't match or the lockfile
# no longer exists, we start again.
# This implementation is unfair since the last person to request the
# lock is the most likely to win it.
# pylint: disable=broad-except
# we disable the broad-except because we want to actually catch all possible exceptions
try:
lock_file = open(name, 'a+')
fileno = lock_file.fileno()
fcntl.flock(fileno, operation)
statinfo = os.fstat(fileno)
if os.path.exists(lock_file.name):
statinfo2 = os.stat(lock_file.name)
if statinfo.st_ino == statinfo2.st_ino:
return lock_file
lock_file.close()
except Exception as exc:
try:
lock_file.close()
except Exception as exc2:
config.logger.error("Failed to close the lockfile: %s", exc2)
config.logger.error("Failed to acquire the lockfile: %s", exc)
if not retry:
return None
评论列表
文章目录