about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-01-01 10:48:53 +0100
committerGitHub <noreply@github.com>2022-01-01 10:48:53 +0100
commit5a5c9282e04711df07beb883eb463a136f91fbf9 (patch)
treef18e5d3a827380c153bce988fefd472118816904 /src/bootstrap
parentad0d4190facd509a5c79dce427bb7deb2824046e (diff)
parent1326bd6484725ed78552cd4b7ed7b5ddb5b5eec9 (diff)
downloadrust-5a5c9282e04711df07beb883eb463a136f91fbf9.tar.gz
rust-5a5c9282e04711df07beb883eb463a136f91fbf9.zip
Rollup merge of #88310 - worldeva:bootstrap-locking, r=Mark-Simulacrum
Lock bootstrap (x.py) build directory

Closes #76661,  closes #80849,
`x.py` creates a lock file at `project_root/lock.db`

r? `@jyn514` , because he was one that told me about this~
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/bootstrap.py42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 5df3d0bde6d..5a33073e6b0 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:
@@ -1228,6 +1264,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