Ver código fonte

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.
Marek Marczykowski-Górecki 4 anos atrás
pai
commit
81559d139c
1 arquivos alterados com 28 adições e 0 exclusões
  1. 28 0
      qubesadmin/utils.py

+ 28 - 0
qubesadmin/utils.py

@@ -23,6 +23,8 @@
 #
 
 """Various utility functions."""
+
+import fcntl
 import os
 import re
 
@@ -164,3 +166,29 @@ def encode_for_vmexec(args):
         part = re.sub(br'[^a-zA-Z0-9_.+]', encode, arg.encode('utf-8'))
         parts.append(part)
     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()