summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian "sp1rit"​ <sp1rit@disroot.org>2024-11-01 12:37:29 +0100
committerJussi Pakkanen <jussi.pakkanen@mailbox.org>2025-06-03 15:43:58 +0300
commit4a14c4faf93361832ecb0134e1c0f58a239b4f15 (patch)
treee24df2730fea2c3d32d299bdccb3b8a6a6075975
parent960509811e3999f83c67607ce2a5a76e2a7bd36e (diff)
downloadmeson-4a14c4faf93361832ecb0134e1c0f58a239b4f15.tar.gz
utils: Replace BuildDirLock with generic DirectoryLock
DirectoryLock provides a generic locking implementation the replaces the previously used BuildDirLock.
-rw-r--r--mesonbuild/msetup.py4
-rw-r--r--mesonbuild/utils/platform.py22
-rw-r--r--mesonbuild/utils/posix.py26
-rw-r--r--mesonbuild/utils/win32.py24
-rw-r--r--unittests/allplatformstests.py7
5 files changed, 56 insertions, 27 deletions
diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py
index d4e745468..32344cae6 100644
--- a/mesonbuild/msetup.py
+++ b/mesonbuild/msetup.py
@@ -188,7 +188,9 @@ class MesonApp:
mlog.set_timestamp_start(time.monotonic())
if self.options.clearcache:
env.coredata.clear_cache()
- with mesonlib.BuildDirLock(self.build_dir):
+ with mesonlib.DirectoryLock(self.build_dir, 'meson-private/meson.lock',
+ mesonlib.DirectoryLockAction.FAIL,
+ 'Some other Meson process is already using this build directory. Exiting.'):
return self._generate(env, capture, vslite_ctx)
def check_unused_options(self, coredata: 'coredata.CoreData', cmd_line_options: T.Any, all_subprojects: T.Mapping[str, object]) -> None:
diff --git a/mesonbuild/utils/platform.py b/mesonbuild/utils/platform.py
index 8e762b63f..8fdfee6e5 100644
--- a/mesonbuild/utils/platform.py
+++ b/mesonbuild/utils/platform.py
@@ -6,22 +6,30 @@ from __future__ import annotations
"""base classes providing no-op functionality.."""
+import enum
import os
import typing as T
from .. import mlog
-__all__ = ['BuildDirLock']
+__all__ = ['DirectoryLock', 'DirectoryLockAction', 'DirectoryLockBase']
-# This needs to be inherited by the specific implementations to make type
-# checking happy
-class BuildDirLock:
+class DirectoryLockAction(enum.Enum):
+ IGNORE = 0
+ WAIT = 1
+ FAIL = 2
- def __init__(self, builddir: str) -> None:
- self.lockfilename = os.path.join(builddir, 'meson-private/meson.lock')
+class DirectoryLockBase:
+ def __init__(self, directory: str, lockfile: str, action: DirectoryLockAction, err: str) -> None:
+ self.action = action
+ self.err = err
+ self.lockpath = os.path.join(directory, lockfile)
def __enter__(self) -> None:
- mlog.debug('Calling the no-op version of BuildDirLock')
+ mlog.debug('Calling the no-op version of DirectoryLock')
def __exit__(self, *args: T.Any) -> None:
pass
+
+class DirectoryLock(DirectoryLockBase):
+ pass
diff --git a/mesonbuild/utils/posix.py b/mesonbuild/utils/posix.py
index e8387ba17..a601dee46 100644
--- a/mesonbuild/utils/posix.py
+++ b/mesonbuild/utils/posix.py
@@ -10,23 +10,33 @@ import fcntl
import typing as T
from .core import MesonException
-from .platform import BuildDirLock as BuildDirLockBase
+from .platform import DirectoryLockBase, DirectoryLockAction
-__all__ = ['BuildDirLock']
+__all__ = ['DirectoryLock', 'DirectoryLockAction']
-class BuildDirLock(BuildDirLockBase):
+class DirectoryLock(DirectoryLockBase):
def __enter__(self) -> None:
- self.lockfile = open(self.lockfilename, 'w', encoding='utf-8')
+ self.lockfile = open(self.lockpath, 'w+', encoding='utf-8')
try:
- fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
- except (BlockingIOError, PermissionError):
+ flags = fcntl.LOCK_EX
+ if self.action != DirectoryLockAction.WAIT:
+ flags = flags | fcntl.LOCK_NB
+ fcntl.flock(self.lockfile, flags)
+ except BlockingIOError:
self.lockfile.close()
- raise MesonException('Some other Meson process is already using this build directory. Exiting.')
+ if self.action == DirectoryLockAction.IGNORE:
+ return
+ raise MesonException(self.err)
+ except PermissionError:
+ self.lockfile.close()
+ raise MesonException(self.err)
except OSError as e:
self.lockfile.close()
- raise MesonException(f'Failed to lock the build directory: {e.strerror}')
+ raise MesonException(f'Failed to lock directory {self.lockpath}: {e.strerror}')
def __exit__(self, *args: T.Any) -> None:
+ if self.lockfile is None or self.lockfile.closed:
+ return
fcntl.flock(self.lockfile, fcntl.LOCK_UN)
self.lockfile.close()
diff --git a/mesonbuild/utils/win32.py b/mesonbuild/utils/win32.py
index 4fcb8ed83..22aea8680 100644
--- a/mesonbuild/utils/win32.py
+++ b/mesonbuild/utils/win32.py
@@ -10,20 +10,30 @@ import msvcrt
import typing as T
from .core import MesonException
-from .platform import BuildDirLock as BuildDirLockBase
+from .platform import DirectoryLockBase, DirectoryLockAction
-__all__ = ['BuildDirLock']
+__all__ = ['DirectoryLock', 'DirectoryLockAction']
-class BuildDirLock(BuildDirLockBase):
+class DirectoryLock(DirectoryLockBase):
def __enter__(self) -> None:
- self.lockfile = open(self.lockfilename, 'w', encoding='utf-8')
+ self.lockfile = open(self.lockpath, 'w+', encoding='utf-8')
try:
- msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1)
- except (BlockingIOError, PermissionError):
+ mode = msvcrt.LK_LOCK
+ if self.action != DirectoryLockAction.WAIT:
+ mode = msvcrt.LK_NBLCK
+ msvcrt.locking(self.lockfile.fileno(), mode, 1)
+ except BlockingIOError:
self.lockfile.close()
- raise MesonException('Some other Meson process is already using this build directory. Exiting.')
+ if self.action == DirectoryLockAction.IGNORE:
+ return
+ raise MesonException(self.err)
+ except PermissionError:
+ self.lockfile.close()
+ raise MesonException(self.err)
def __exit__(self, *args: T.Any) -> None:
+ if self.lockfile is None or self.lockfile.closed:
+ return
msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1)
self.lockfile.close()
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index fa6f11965..536fb612a 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -29,7 +29,7 @@ import mesonbuild.coredata
import mesonbuild.machinefile
import mesonbuild.modules.gnome
from mesonbuild.mesonlib import (
- BuildDirLock, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd,
+ DirectoryLock, DirectoryLockAction, MachineChoice, is_windows, is_osx, is_cygwin, is_dragonflybsd,
is_sunos, windows_proof_rmtree, python_command, version_compare, split_args, quote_arg,
relpath, is_linux, git, search_version, do_conf_file, do_conf_str, default_prefix,
MesonException, EnvironmentException,
@@ -2499,10 +2499,9 @@ class AllPlatformTests(BasePlatformTests):
def test_flock(self):
exception_raised = False
with tempfile.TemporaryDirectory() as tdir:
- os.mkdir(os.path.join(tdir, 'meson-private'))
- with BuildDirLock(tdir):
+ with DirectoryLock(tdir, 'lock', DirectoryLockAction.FAIL, 'failed to lock directory'):
try:
- with BuildDirLock(tdir):
+ with DirectoryLock(tdir, 'lock', DirectoryLockAction.FAIL, 'expected failure'):
pass
except MesonException:
exception_raised = True