From 79156254e2585d58764661b3b7d7d4a90380c604 Mon Sep 17 00:00:00 2001 From: Piotr Batko <pbatko@syncad.com> Date: Fri, 29 Jul 2022 13:59:48 +0200 Subject: [PATCH] Remove race condition during creation of directory for SQLiteFile When multiple instances of beem was run in parallel, following error appeared from time to time (the detailed content of error is attached at the very bottom): ``` > mkdir(name, mode) E FileExistsError: [Errno 17] File exists: '/root/.local/share/beem' /usr/lib/python3.8/os.py:223: FileExistsError ``` I assume that problem occured, because two processes at the same time checked if directory exists. Both received same answer -- directory doesn't exists. So first successfully created the directory, and second one failed with this error. Solution implemented in this commit, is to accept situation, when directory already exists. Detailed error description: ``` /builds/hive/hive/venv/lib/python3.8/site-packages/beem-0.24.22-py3.8.egg/beem/blockchaininstance.py:186: in __init__ self.config = kwargs.get("config_store", get_default_config_store(**kwargs)) /builds/hive/hive/venv/lib/python3.8/site-packages/beem-0.24.22-py3.8.egg/beem/storage.py:46: in get_default_config_store return generate_config_store(SqliteConfigurationStore, blockchain="hive")(*args, **kwargs) /builds/hive/hive/venv/lib/python3.8/site-packages/beem-0.24.22-py3.8.egg/beemstorage/sqlite.py:198: in __init__ SQLiteFile.__init__(self, *args, **kwargs) /builds/hive/hive/venv/lib/python3.8/site-packages/beem-0.24.22-py3.8.egg/beemstorage/sqlite.py:59: in __init__ os.makedirs(self.data_dir) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = '/root/.local/share/beem', mode = 511, exist_ok = False def makedirs(name, mode=0o777, exist_ok=False): """makedirs(name [, mode=0o777][, exist_ok=False]) Super-mkdir; create a leaf directory and all intermediate ones. Works like mkdir, except that any intermediate path segment (not just the rightmost) will be created if it does not exist. If the target directory already exists, raise an OSError if exist_ok is False. Otherwise no exception is raised. This is recursive. """ head, tail = path.split(name) if not tail: head, tail = path.split(head) if head and tail and not path.exists(head): try: makedirs(head, exist_ok=exist_ok) except FileExistsError: # Defeats race condition when another thread created the path pass cdir = curdir if isinstance(tail, bytes): cdir = bytes(curdir, 'ASCII') if tail == cdir: # xxx/newdir/. exists if xxx/newdir exists return try: > mkdir(name, mode) E FileExistsError: [Errno 17] File exists: '/root/.local/share/beem' /usr/lib/python3.8/os.py:223: FileExistsError ``` --- beemstorage/sqlite.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/beemstorage/sqlite.py b/beemstorage/sqlite.py index 336a9931..12829343 100644 --- a/beemstorage/sqlite.py +++ b/beemstorage/sqlite.py @@ -50,13 +50,8 @@ class SQLiteFile: self.sqlite_file = os.path.join(self.data_dir, self.storageDatabase) - """ Ensure that the directory in which the data is stored - exists - """ - if os.path.isdir(self.data_dir): # pragma: no cover - return - else: # pragma: no cover - os.makedirs(self.data_dir) + # Ensure that the directory in which the data is stored exists + os.makedirs(self.data_dir, exist_ok=True) def sqlite3_backup(self, backupdir): """ Create timestamped database copy -- GitLab