diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2018-03-18 20:13:00 +0200 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2018-03-20 22:28:37 +0200 |
commit | 58156ef7cfd56ddcbd230c510f363f49a2c172fd (patch) | |
tree | 5761bcf68322f044c3ea50616486e2323c10f9e1 | |
parent | 1c8d4bf05b85b0e9f7dc5b1438f4e33b515db668 (diff) | |
download | meson-58156ef7cfd56ddcbd230c510f363f49a2c172fd.zip meson-58156ef7cfd56ddcbd230c510f363f49a2c172fd.tar.gz meson-58156ef7cfd56ddcbd230c510f363f49a2c172fd.tar.bz2 |
Grab a file lock on the build dir during modifications.
-rw-r--r-- | mesonbuild/mesonlib.py | 38 | ||||
-rw-r--r-- | mesonbuild/mesonmain.py | 3 | ||||
-rwxr-xr-x | run_unittests.py | 13 |
3 files changed, 53 insertions, 1 deletions
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py index 247b4f9..a076e3e 100644 --- a/mesonbuild/mesonlib.py +++ b/mesonbuild/mesonlib.py @@ -21,6 +21,21 @@ import platform, subprocess, operator, os, shutil, re import collections from mesonbuild import mlog +have_fcntl = False +have_msvcrt = False + +try: + import fcntl + have_fcntl = True +except Exception: + pass + +try: + import msvcrt + have_msvcrt = True +except Exception: + pass + from glob import glob def detect_meson_py_location(): @@ -978,3 +993,26 @@ class OrderedSet(collections.MutableSet): def difference(self, set_): return type(self)(e for e in self if e not in set_) + +class BuildDirLock: + + def __init__(self, builddir): + self.lockfilename = os.path.join(builddir, 'meson-private/meson.lock') + + def __enter__(self): + self.lockfile = open(self.lockfilename, 'w') + try: + if have_fcntl: + fcntl.flock(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB) + elif have_msvcrt: + msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_NBLCK, 1) + except (BlockingIOError, PermissionError): + self.lockfile.close() + raise MesonException('Some other Meson process is already using this build directory. Exiting.') + + def __exit__(self, *args): + if have_fcntl: + fcntl.flock(self.lockfile, fcntl.LOCK_UN) + elif have_msvcrt: + msvcrt.locking(self.lockfile.fileno(), msvcrt.LK_UNLCK, 1) + self.lockfile.close() diff --git a/mesonbuild/mesonmain.py b/mesonbuild/mesonmain.py index 9c4498c..651224e 100644 --- a/mesonbuild/mesonmain.py +++ b/mesonbuild/mesonmain.py @@ -147,7 +147,8 @@ class MesonApp: def generate(self): env = environment.Environment(self.source_dir, self.build_dir, self.meson_script_launcher, self.options, self.original_cmd_line_args) mlog.initialize(env.get_log_dir()) - self._generate(env) + with mesonlib.BuildDirLock(self.build_dir): + self._generate(env) def _generate(self, env): mlog.debug('Build started at', datetime.datetime.now().isoformat()) diff --git a/run_unittests.py b/run_unittests.py index 3ea0412..b6367c1 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -37,6 +37,7 @@ from mesonbuild.interpreter import ObjectHolder from mesonbuild.mesonlib import ( is_windows, is_osx, is_cygwin, is_dragonflybsd, windows_proof_rmtree, python_command, meson_command, version_compare, + BuildDirLock ) from mesonbuild.environment import Environment, detect_ninja from mesonbuild.mesonlib import MesonException, EnvironmentException @@ -1882,6 +1883,18 @@ int main(int argc, char **argv) { self.init(testdir, extra_args=['--layout=flat']) self.build() + def test_flock(self): + exception_raised = False + with tempfile.TemporaryDirectory() as tdir: + os.mkdir(os.path.join(tdir, 'meson-private')) + with BuildDirLock(tdir): + try: + with BuildDirLock(tdir): + pass + except MesonException: + exception_raised = True + self.assertTrue(exception_raised, 'Double locking did not raise exception.') + class FailureTests(BasePlatformTests): ''' |