summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/test/lldbtest.py32
-rw-r--r--lldb/test/lock.py8
2 files changed, 36 insertions, 4 deletions
diff --git a/lldb/test/lldbtest.py b/lldb/test/lldbtest.py
index 560c830a50b..6f949b25424 100644
--- a/lldb/test/lldbtest.py
+++ b/lldb/test/lldbtest.py
@@ -33,6 +33,7 @@ $
import abc
import glob
+import lock
import os, sys, traceback
import os.path
import re
@@ -47,6 +48,14 @@ import lldbtest_config
import lldbutil
from _pyio import __metaclass__
+# dosep.py starts lots and lots of dotest instances
+# This option helps you find if two (or more) dotest instances are using the same
+# directory at the same time
+# Enable it to cause test failures and stderr messages if dotest instances try to run in
+# the same directory simultaneously
+# it is disabled by default because it litters the test directories with ".dirlock" files
+debug_confirm_directory_exclusivity = False
+
# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir' options.
@@ -936,7 +945,6 @@ class Base(unittest2.TestCase):
Python unittest framework class setup fixture.
Do current directory manipulation.
"""
-
# Fail fast if 'mydir' attribute is not overridden.
if not cls.mydir or len(cls.mydir) == 0:
raise Exception("Subclasses must override the 'mydir' attribute.")
@@ -947,10 +955,26 @@ class Base(unittest2.TestCase):
# Change current working directory if ${LLDB_TEST} is defined.
# See also dotest.py which sets up ${LLDB_TEST}.
if ("LLDB_TEST" in os.environ):
+ full_dir = os.path.join(os.environ["LLDB_TEST"], cls.mydir)
if traceAlways:
- print >> sys.stderr, "Change dir to:", os.path.join(os.environ["LLDB_TEST"], cls.mydir)
+ print >> sys.stderr, "Change dir to:", full_dir
os.chdir(os.path.join(os.environ["LLDB_TEST"], cls.mydir))
+ if debug_confirm_directory_exclusivity:
+ cls.dir_lock = lock.Lock(os.path.join(full_dir, ".dirlock"))
+ try:
+ cls.dir_lock.try_acquire()
+ # write the class that owns the lock into the lock file
+ cls.dir_lock.handle.write(cls.__name__)
+ except IOError as ioerror:
+ # nothing else should have this directory lock
+ # wait here until we get a lock
+ cls.dir_lock.acquire()
+ # read the previous owner from the lock file
+ lock_id = cls.dir_lock.handle.read()
+ print >> sys.stderr, "LOCK ERROR: {} wants to lock '{}' but it is already locked by '{}'".format(cls.__name__, full_dir, lock_id)
+ raise ioerror
+
# Set platform context.
if platformIsDarwin():
cls.platformContext = _PlatformContext('DYLD_LIBRARY_PATH', 'lib', 'dylib')
@@ -982,6 +1006,10 @@ class Base(unittest2.TestCase):
exc_type, exc_value, exc_tb = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_tb)
+ if debug_confirm_directory_exclusivity:
+ cls.dir_lock.release()
+ del cls.dir_lock
+
# Restore old working directory.
if traceAlways:
print >> sys.stderr, "Restore dir to:", cls.oldcwd
diff --git a/lldb/test/lock.py b/lldb/test/lock.py
index 06e2b8cafaa..89823b88abc 100644
--- a/lldb/test/lock.py
+++ b/lldb/test/lock.py
@@ -10,12 +10,16 @@ class Lock:
def __init__(self, filename):
self.filename = filename
# This will create it if it does not exist already
- self.handle = open(filename, 'w')
+ unbuffered = 0
+ self.handle = open(filename, 'a+', unbuffered)
- # Bitwise OR fcntl.LOCK_NB if you need a non-blocking lock
def acquire(self):
fcntl.flock(self.handle, fcntl.LOCK_EX)
+ # will throw IOError if unavailable
+ def try_acquire(self):
+ fcntl.flock(self.handle, fcntl.LOCK_NB | fcntl.LOCK_EX)
+
def release(self):
fcntl.flock(self.handle, fcntl.LOCK_UN)
OpenPOWER on IntegriCloud