X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fbootstrap%2Fbootstrap.py;h=5235a6b8180533ea4269aa35ef423fdeb65637eb;hb=1591dcb659917de87254297073b078b9ade56612;hp=5df3d0bde6d58725cb4715b640614dbb9b921720;hpb=521fdcbe4ddaa717be2acbeb30f8978d6378fea1;p=rust.git diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5df3d0bde6d..5235a6b8180 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -15,6 +15,42 @@ import tempfile from time import time +# 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 + def support_xz(): try: with tempfile.NamedTemporaryFile(delete=False) as temp_file: @@ -938,6 +974,7 @@ class RustBuild(object): def build_bootstrap(self): """Build bootstrap""" + print("Building rustbuild") build_dir = os.path.join(self.build_dir, "bootstrap") if self.clean and os.path.exists(build_dir): shutil.rmtree(build_dir) @@ -1097,7 +1134,7 @@ class RustBuild(object): recorded_submodules[data[3]] = data[2] for module in filtered_submodules: self.update_submodule(module[0], module[1], recorded_submodules) - print("Submodules updated in %.2f seconds" % (time() - start_time)) + print(" Submodules updated in %.2f seconds" % (time() - start_time)) def set_dist_environment(self, url): """Set download URL for normal environment""" @@ -1228,6 +1265,12 @@ def bootstrap(help_triggered): build.set_dist_environment(data["dist_server"]) build.build = args.build or build.build_triple() + + # Acquire the lock before doing any build actions + # The lock is released when `lock` is dropped + if not os.path.exists(build.build_dir): + os.makedirs(build.build_dir) + lock = acquire_lock(build.build_dir) build.update_submodules() # Fetch/build the bootstrap