From dcb1743764fc74828a2293b2929b6d667ad61d55 Mon Sep 17 00:00:00 2001 From: Alessandro Comodi Date: Fri, 4 Mar 2022 12:40:22 +0100 Subject: [PATCH] add file locking system to avoid race conditions on db files Signed-off-by: Alessandro Comodi --- prjxray/tile_segbits.py | 7 +++++++ prjxray/util.py | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/prjxray/tile_segbits.py b/prjxray/tile_segbits.py index b9f940b7..8fd6b151 100644 --- a/prjxray/tile_segbits.py +++ b/prjxray/tile_segbits.py @@ -10,6 +10,7 @@ # SPDX-License-Identifier: ISC from collections import namedtuple from prjxray import bitstream +from prjxray import util from prjxray.grid_types import BlockType import enum @@ -84,15 +85,21 @@ class TileSegbits(object): if tile_db.ppips is not None: with open(tile_db.ppips) as f: + util.lock_file(f, 10) self.ppips = read_ppips(f) + util.unlock_file(f) if tile_db.segbits is not None: with open(tile_db.segbits) as f: + util.lock_file(f, 10) self.segbits[BlockType.CLB_IO_CLK] = read_segbits(f) + util.unlock_file(f) if tile_db.block_ram_segbits is not None: with open(tile_db.block_ram_segbits) as f: + util.lock_file(f, 10) self.segbits[BlockType.BLOCK_RAM] = read_segbits(f) + util.unlock_file(f) for block_type in self.segbits: for feature in self.segbits[block_type]: diff --git a/prjxray/util.py b/prjxray/util.py index 6c285795..5ce4550a 100644 --- a/prjxray/util.py +++ b/prjxray/util.py @@ -8,10 +8,12 @@ # https://opensource.org/licenses/ISC # # SPDX-License-Identifier: ISC +import fcntl import math import os import random import re +import signal import yaml from .roi import Roi @@ -254,8 +256,10 @@ def parse_db_line(line): def parse_db_lines(fn): with open(fn, "r") as f: + lock_file(f, 10) for line in f: yield line, parse_db_line(line) + unlock_file(f) def write_db_lines(fn, entries, track_origin=False): @@ -269,8 +273,10 @@ def write_db_lines(fn, entries, track_origin=False): new_lines.append(new_line) with open(fn, "w") as f: + lock_file(f, 10) for line in sorted(new_lines): print(line, file=f) + unlock_file(f) def parse_tagbit(x): @@ -402,3 +408,22 @@ def add_bool_arg(parser, yes_arg, default=False, **kwargs): yes_arg, dest=dest, action='store_true', default=default, **kwargs) parser.add_argument( '--no-' + dashed, dest=dest, action='store_false', **kwargs) + + +def timeout_handler(signum, frame): + raise Exception("ERROR: could not lock file!") + + +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 unlock_file(fd): + fcntl.flock(fd.fileno(), fcntl.LOCK_UN)