|
15 | 15 |
|
16 | 16 | from time import time
|
17 | 17 |
|
| 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 | + |
18 | 54 | def support_xz():
|
19 | 55 | try:
|
20 | 56 | with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
@@ -1228,6 +1264,12 @@ def bootstrap(help_triggered):
|
1228 | 1264 | build.set_dist_environment(data["dist_server"])
|
1229 | 1265 |
|
1230 | 1266 | build.build = args.build or build.build_triple()
|
| 1267 | + |
| 1268 | + # Acquire the lock before doing any build actions |
| 1269 | + # The lock is released when `lock` is dropped |
| 1270 | + if not os.path.exists(build.build_dir): |
| 1271 | + os.makedirs(build.build_dir) |
| 1272 | + lock = acquire_lock(build.build_dir) |
1231 | 1273 | build.update_submodules()
|
1232 | 1274 |
|
1233 | 1275 | # Fetch/build the bootstrap
|
|
0 commit comments