utils: add simple locking primitive

Standard python locking modules do not provide detection if lock-holding
process is still alive. Add a simple wrapper around fcntl.lockf that do
just that.
This commit is contained in:
Marek Marczykowski-Górecki 2019-09-08 05:26:49 +02:00
parent 6338b936e2
commit 81559d139c
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -23,6 +23,8 @@
# #
"""Various utility functions.""" """Various utility functions."""
import fcntl
import os import os
import re import re
@ -164,3 +166,29 @@ def encode_for_vmexec(args):
part = re.sub(br'[^a-zA-Z0-9_.+]', encode, arg.encode('utf-8')) part = re.sub(br'[^a-zA-Z0-9_.+]', encode, arg.encode('utf-8'))
parts.append(part) parts.append(part)
return b'+'.join(parts).decode('ascii') return b'+'.join(parts).decode('ascii')
class LockFile(object):
"""Simple locking context manager. It opens a file with an advisory lock
taken (fcntl.lockf)"""
def __init__(self, path, nonblock=False):
"""Open the file. Call *acquire* or enter the context to lock
the file"""
self.file = open(path, "w")
self.nonblock = nonblock
def __enter__(self, *args, **kwargs):
self.acquire()
return self
def acquire(self):
"""Lock the opened file"""
fcntl.lockf(self.file,
fcntl.LOCK_EX | (fcntl.LOCK_NB if self.nonblock else 0))
def __exit__(self, exc_type=None, exc_value=None, traceback=None):
self.release()
def release(self):
"""Unlock the file and close the file object"""
fcntl.lockf(self.file, fcntl.LOCK_UN)
self.file.close()