about summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorJosh Triplett <josh@joshtriplett.org>2025-08-14 17:51:48 -0700
committerJosh Triplett <josh@joshtriplett.org>2025-08-14 20:55:02 -0700
commitffdc40f30ab3ed1b4b1b7e5b2c877f21fe4e38ef (patch)
treedaa345fe61bbce4e84d189cc2ece923519d0ebb1 /src/bootstrap
parent3507a749b365aae4eefa96ab700a9315d3280ee7 (diff)
downloadrust-ffdc40f30ab3ed1b4b1b7e5b2c877f21fe4e38ef.tar.gz
rust-ffdc40f30ab3ed1b4b1b7e5b2c877f21fe4e38ef.zip
bootstrap: Switch from fd-lock to native locking in std
In the process, fix a race condition, by never truncating or writing to
the file unless we currently hold the lock.
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/Cargo.lock12
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/src/bin/main.rs46
3 files changed, 21 insertions, 38 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 537f4b6184f..e5f95b87273 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -48,7 +48,6 @@ dependencies = [
  "clap",
  "clap_complete",
  "cmake",
- "fd-lock",
  "home",
  "ignore",
  "insta",
@@ -269,17 +268,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
 
 [[package]]
-name = "fd-lock"
-version = "4.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78"
-dependencies = [
- "cfg-if",
- "rustix",
- "windows-sys 0.59.0",
-]
-
-[[package]]
 name = "filetime"
 version = "0.2.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index bdf0b42255e..60c3548e16d 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -38,7 +38,6 @@ cmake = "=0.1.54"
 build_helper = { path = "../build_helper" }
 clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
 clap_complete = "4.4"
-fd-lock = "4.0"
 home = "0.5"
 ignore = "0.4"
 libc = "0.2"
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index 8b2d67266a7..93c7faf4f01 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -5,8 +5,8 @@
 //! parent directory, and otherwise documentation can be found throughout the `build`
 //! directory in each respective module.
 
-use std::fs::{self, OpenOptions};
-use std::io::{self, BufRead, BufReader, IsTerminal, Write};
+use std::fs::{self, OpenOptions, TryLockError};
+use std::io::{self, BufRead, BufReader, IsTerminal, Read, Write};
 use std::path::Path;
 use std::str::FromStr;
 use std::time::Instant;
@@ -39,38 +39,34 @@ fn main() {
     let config = Config::parse(flags);
 
     let mut build_lock;
-    let _build_lock_guard;
 
     if !config.bypass_bootstrap_lock {
         // Display PID of process holding the lock
         // PID will be stored in a lock file
         let lock_path = config.out.join("lock");
-        let pid = fs::read_to_string(&lock_path);
-
-        build_lock = fd_lock::RwLock::new(t!(fs::OpenOptions::new()
+        build_lock = t!(fs::OpenOptions::new()
+            .read(true)
             .write(true)
-            .truncate(true)
             .create(true)
-            .open(&lock_path)));
-        _build_lock_guard = match build_lock.try_write() {
-            Ok(mut lock) => {
-                t!(lock.write(process::id().to_string().as_ref()));
-                lock
+            .truncate(false)
+            .open(&lock_path));
+        t!(build_lock.try_lock().or_else(|e| {
+            if let TryLockError::Error(e) = e {
+                return Err(e);
             }
-            err => {
-                drop(err);
-                // #135972: We can reach this point when the lock has been taken,
-                // but the locker has not yet written its PID to the file
-                if let Some(pid) = pid.ok().filter(|pid| !pid.is_empty()) {
-                    println!("WARNING: build directory locked by process {pid}, waiting for lock");
-                } else {
-                    println!("WARNING: build directory locked, waiting for lock");
-                }
-                let mut lock = t!(build_lock.write());
-                t!(lock.write(process::id().to_string().as_ref()));
-                lock
+            let mut pid = String::new();
+            t!(build_lock.read_to_string(&mut pid));
+            // #135972: We can reach this point when the lock has been taken,
+            // but the locker has not yet written its PID to the file
+            if !pid.is_empty() {
+                println!("WARNING: build directory locked by process {pid}, waiting for lock");
+            } else {
+                println!("WARNING: build directory locked, waiting for lock");
             }
-        };
+            build_lock.lock()
+        }));
+        t!(build_lock.set_len(0));
+        t!(build_lock.write_all(process::id().to_string().as_bytes()));
     }
 
     // check_version warnings are not printed during setup, or during CI