+# Acquire a lock on the build directory to make sure that
+# we don't cause a race condition while building
+# Lock is created in `build_dir/lock.db`
+def acquire_lock(build_dir):
+ try:
+ import sqlite3
+
+ path = os.path.join(build_dir, "lock.db")
+ try:
+ con = sqlite3.Connection(path, timeout=0)
+ curs = con.cursor()
+ curs.execute("BEGIN EXCLUSIVE")
+ # The lock is released when the cursor is dropped
+ return curs
+ # If the database is busy then lock has already been acquired
+ # so we wait for the lock.
+ # We retry every quarter second so that execution is passed back to python
+ # so that it can handle signals
+ except sqlite3.OperationalError:
+ del con
+ del curs
+ print("Waiting for lock on build directory")
+ con = sqlite3.Connection(path, timeout=0.25)
+ curs = con.cursor()
+ while True:
+ try:
+ curs.execute("BEGIN EXCLUSIVE")
+ except sqlite3.OperationalError:
+ pass
+ return curs
+ except ImportError:
+ print("warning: sqlite3 not available in python, skipping build directory lock")
+ print("please file an issue on rust-lang/rust")
+ print("this is not a problem for non-concurrent x.py invocations")
+ return None
+