aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2018-03-18 20:13:00 +0200
committerJussi Pakkanen <jpakkane@gmail.com>2018-03-20 22:28:37 +0200
commit58156ef7cfd56ddcbd230c510f363f49a2c172fd (patch)
tree5761bcf68322f044c3ea50616486e2323c10f9e1
parent1c8d4bf05b85b0e9f7dc5b1438f4e33b515db668 (diff)
downloadmeson-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.py38
-rw-r--r--mesonbuild/mesonmain.py3
-rwxr-xr-xrun_unittests.py13
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):
'''