diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 57113b0ec62c6..8637a86cb5cbf 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -29,12 +29,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - [[package]] name = "block-buffer" version = "0.10.2" @@ -53,8 +47,8 @@ dependencies = [ "clap", "clap_complete", "cmake", - "fd-lock", "filetime", + "fs2", "hex", "home", "ignore", @@ -245,27 +239,6 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "errno" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fd-lock" -version = "3.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef033ed5e9bad94e55838ca0ca906db0e043f517adda0c8b79c7a8c66c93c1b5" -dependencies = [ - "cfg-if", - "rustix", - "windows-sys", -] - [[package]] name = "filetime" version = "0.2.16" @@ -284,6 +257,16 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "generic-array" version = "0.14.5" @@ -374,12 +357,6 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" -[[package]] -name = "linux-raw-sys" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" - [[package]] name = "log" version = "0.4.17" @@ -509,7 +486,7 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -535,19 +512,6 @@ version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" -[[package]] -name = "rustix" -version = "0.38.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "ryu" version = "1.0.10" @@ -757,15 +721,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-targets" version = "0.48.5" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index e4d359141cec1..e4f7991368bb4 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -39,6 +39,7 @@ clap = { version = "4.4.7", default-features = false, features = ["std", "usage" clap_complete = "4.4.3" cmake = "0.1.38" filetime = "0.2" +fs2 = "0.4.3" hex = "0.4" home = "0.5.4" ignore = "0.4.10" @@ -62,10 +63,6 @@ xz2 = "0.1" # Dependencies needed by the build-metrics feature sysinfo = { version = "0.26.0", optional = true } -# Solaris doesn't support flock() and thus fd-lock is not option now -[target.'cfg(not(target_os = "solaris"))'.dependencies] -fd-lock = "3.0.13" - [target.'cfg(windows)'.dependencies.junction] version = "1.0.0" diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index 952ef40ed424d..76c32a8a21c97 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -5,9 +5,7 @@ //! parent directory, and otherwise documentation can be found throughout the `build` //! directory in each respective module. -#[cfg(all(any(unix, windows), not(target_os = "solaris")))] use std::io::Write; -#[cfg(all(any(unix, windows), not(target_os = "solaris")))] use std::process; use std::{ env, fs, @@ -15,46 +13,32 @@ use std::{ }; use bootstrap::{ - find_recent_config_change_ids, t, Build, Config, Subcommand, CONFIG_CHANGE_HISTORY, + find_recent_config_change_ids, t, Build, Config, FileLock, Subcommand, CONFIG_CHANGE_HISTORY, }; fn main() { let args = env::args().skip(1).collect::>(); let config = Config::parse(&args); - #[cfg(all(any(unix, windows), not(target_os = "solaris")))] - let mut build_lock; - #[cfg(all(any(unix, windows), not(target_os = "solaris")))] - let _build_lock_guard; - #[cfg(all(any(unix, windows), not(target_os = "solaris")))] + let lock_path = config.out.join("lock"); // Display PID of process holding the lock // PID will be stored in a lock file - { - let path = config.out.join("lock"); - let pid = match fs::read_to_string(&path) { - Ok(contents) => contents, - Err(_) => String::new(), - }; - - build_lock = - fd_lock::RwLock::new(t!(fs::OpenOptions::new().write(true).create(true).open(&path))); - _build_lock_guard = match build_lock.try_write() { - Ok(mut lock) => { - t!(lock.write(&process::id().to_string().as_ref())); - lock - } - err => { - drop(err); - println!("WARNING: build directory locked by process {pid}, waiting for lock"); - let mut lock = t!(build_lock.write()); - t!(lock.write(&process::id().to_string().as_ref())); - lock - } - }; - } + let pid = fs::read_to_string(&lock_path).unwrap_or_default(); + + let mut build_lock: FileLock = + t!(fs::OpenOptions::new().write(true).create(true).open(&lock_path)).into(); - #[cfg(any(not(any(unix, windows)), target_os = "solaris"))] - println!("WARNING: file locking not supported for target, not locking build directory"); + match build_lock.try_lock() { + Ok(mut file) => { + t!(file.write(&process::id().to_string().as_ref())); + } + err => { + drop(err); + println!("WARNING: build directory locked by process {pid}, waiting for lock"); + let mut file = t!(build_lock.lock()); + t!(file.write(&process::id().to_string().as_ref())); + } + }; // check_version warnings are not printed during setup let changelog_suggestion = diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 480dd75791517..609d2ce51db58 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -51,6 +51,7 @@ pub use core::builder::PathSet; pub use core::config::flags::Subcommand; pub use core::config::Config; pub use utils::change_tracker::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY}; +pub use utils::file_lock::FileLock; const LLVM_TOOLS: &[&str] = &[ "llvm-cov", // used to generate coverage report diff --git a/src/bootstrap/src/utils/file_lock.rs b/src/bootstrap/src/utils/file_lock.rs new file mode 100644 index 0000000000000..a6b9c5779a1c4 --- /dev/null +++ b/src/bootstrap/src/utils/file_lock.rs @@ -0,0 +1,36 @@ +//! This module provides a `FileLock` type, serving as a cross-platform file-locking wrapper +//! for `std::fs::File`, built on top of the `fs2` crate. +//! +//! Locks are automatically released with the `Drop` trait implementation. + +use std::{fs::File, io}; + +use fs2::FileExt; + +use crate::t; + +pub struct FileLock(File); + +impl FileLock { + pub fn lock(&mut self) -> io::Result<&File> { + self.0.lock_exclusive()?; + Ok(&self.0) + } + + pub fn try_lock(&mut self) -> io::Result<&File> { + self.0.try_lock_exclusive()?; + Ok(&self.0) + } +} + +impl Drop for FileLock { + fn drop(&mut self) { + t!(self.0.unlock()); + } +} + +impl From for FileLock { + fn from(file: File) -> Self { + Self(file) + } +} diff --git a/src/bootstrap/src/utils/mod.rs b/src/bootstrap/src/utils/mod.rs index cb535f0e1632a..9f220c9c6d608 100644 --- a/src/bootstrap/src/utils/mod.rs +++ b/src/bootstrap/src/utils/mod.rs @@ -8,6 +8,7 @@ pub(crate) mod change_tracker; pub(crate) mod channel; pub(crate) mod dylib; pub(crate) mod exec; +pub(crate) mod file_lock; pub(crate) mod helpers; pub(crate) mod job; #[cfg(feature = "build-metrics")]