From 6e026bf30e66541fd6255a691f0116dacce327ad Mon Sep 17 00:00:00 2001 From: Alessandro Comodi Date: Tue, 15 Mar 2022 10:21:20 +0100 Subject: [PATCH] util: add open safe file class Signed-off-by: Alessandro Comodi --- prjxray/util.py | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/prjxray/util.py b/prjxray/util.py index 5ce4550a..fb722c97 100644 --- a/prjxray/util.py +++ b/prjxray/util.py @@ -413,17 +413,40 @@ def add_bool_arg(parser, yes_arg, default=False, **kwargs): def timeout_handler(signum, frame): raise Exception("ERROR: could not lock file!") +class OpenSafeFile: + """ + Opens a file in a thread-safe mode, allowing for safe read and writes + to a file that can potentially be modified by multiple processes at + the same time. + """ -def lock_file(fd, timeout): - try: - signal.signal(signal.SIGALRM, timeout_handler) - signal.alarm(timeout) - fcntl.flock(fd.fileno(), fcntl.LOCK_EX) - signal.alarm(0) - except Exception as e: - print(e) - exit(1) + def __init__(self, name, mode, timeout=10): + self.name = name + self.mode = mode + self.timeout = timeout + self.fd = None -def unlock_file(fd): - fcntl.flock(fd.fileno(), fcntl.LOCK_UN) + def __enter__(self): + self.fd = open(self.name, self.mode) + self.lock_file() + return self.fd + + def __exit__(self): + self.unlock_file() + self.fd.close() + + def lock_file(self): + assert self.fd is not None + try: + signal.signal(signal.SIGALRM, timeout_handler) + signal.alarm(timeout) + fcntl.flock(self.fd.fileno(), fcntl.LOCK_EX) + signal.alarm(0) + except Exception as e: + print(e) + exit(1) + + def unlock_file(self): + assert self.fd is not None + fcntl.flock(self.fd.fileno(), fcntl.LOCK_UN)