Skip to content

Commit 1326bd6

Browse files
worldevaMark-Simulacrum
authored andcommittedDec 31, 2021
Lock x.py build state
Prevent spurious build failures and other bugs caused by parallel runs of x.py. We back the lock with sqlite, so that we have a cross-platform locking strategy, and which can be done nearly first in the build process (from Python), which helps move the lock as early as possible.
1 parent 772d51f commit 1326bd6

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed
 

‎src/bootstrap/bootstrap.py

+42
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@
1515

1616
from time import time
1717

18+
# Acquire a lock on the build directory to make sure that
19+
# we don't cause a race condition while building
20+
# Lock is created in `build_dir/lock.db`
21+
def acquire_lock(build_dir):
22+
try:
23+
import sqlite3
24+
25+
path = os.path.join(build_dir, "lock.db")
26+
try:
27+
con = sqlite3.Connection(path, timeout=0)
28+
curs = con.cursor()
29+
curs.execute("BEGIN EXCLUSIVE")
30+
# The lock is released when the cursor is dropped
31+
return curs
32+
# If the database is busy then lock has already been acquired
33+
# so we wait for the lock.
34+
# We retry every quarter second so that execution is passed back to python
35+
# so that it can handle signals
36+
except sqlite3.OperationalError:
37+
del con
38+
del curs
39+
print("Waiting for lock on build directory")
40+
con = sqlite3.Connection(path, timeout=0.25)
41+
curs = con.cursor()
42+
while True:
43+
try:
44+
curs.execute("BEGIN EXCLUSIVE")
45+
except sqlite3.OperationalError:
46+
pass
47+
return curs
48+
except ImportError:
49+
print("warning: sqlite3 not available in python, skipping build directory lock")
50+
print("please file an issue on rust-lang/rust")
51+
print("this is not a problem for non-concurrent x.py invocations")
52+
return None
53+
1854
def support_xz():
1955
try:
2056
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
@@ -1225,6 +1261,12 @@ def bootstrap(help_triggered):
12251261
build.set_dist_environment(data["dist_server"])
12261262

12271263
build.build = args.build or build.build_triple()
1264+
1265+
# Acquire the lock before doing any build actions
1266+
# The lock is released when `lock` is dropped
1267+
if not os.path.exists(build.build_dir):
1268+
os.makedirs(build.build_dir)
1269+
lock = acquire_lock(build.build_dir)
12281270
build.update_submodules()
12291271

12301272
# Fetch/build the bootstrap

0 commit comments

Comments
 (0)
Please sign in to comment.