From 125fc142ba6230853d65ac9898c41528de6c8c77 Mon Sep 17 00:00:00 2001 From: Nahor Date: Sat, 15 Nov 2025 08:49:24 -0800 Subject: [PATCH] Add mutex around `flock` on Cygwin Issue #11933 stems from Cygwin's flock implementation not being thread safe. Previous code fixed the worst behavior (deadlock), at least in some circumstance but still failed the history tests. This new workaround correctly make flock usage thread safe by surrounding it with a mutex lock. The failing test can now pass and is much faster (5s instead of 15 on my machine) Upstream bug report: https://cygwin.com/pipermail/cygwin/2025-November/258963.html Closes #12068 Closes #11933 --- src/fs.rs | 22 +++++++++++++--------- src/history/history.rs | 5 ----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/fs.rs b/src/fs.rs index 2c79199cf..bc3ccf64f 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -144,17 +144,21 @@ pub fn new(locking_mode: LockingMode, file_path: &wstr) -> std::io::Result // This is required to avoid racing modifications by other threads/processes. let dir_fd = wopen_cloexec(dir_path, OFlag::O_RDONLY, Mode::empty())?; - // Try locking the directory. Retry if locking was interrupted. - while unsafe { libc::flock(dir_fd.as_raw_fd(), locking_mode.flock_op()) } == -1 { - let err = std::io::Error::last_os_error(); - if err.kind() != std::io::ErrorKind::Interrupted { - return Err(err); + { + // Cygwin's `flock` is currently not thread safe (#11933) + #[cfg(cygwin)] + static FLOCK_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(()); + #[cfg(cygwin)] + let _lock = FLOCK_LOCK.lock().unwrap(); + + // Try locking the directory. Retry if locking was interrupted. + while unsafe { libc::flock(dir_fd.as_raw_fd(), locking_mode.flock_op()) } == -1 { + let err = std::io::Error::last_os_error(); + if err.kind() != std::io::ErrorKind::Interrupted { + return Err(err); + } } } - #[cfg(cygwin)] - // Prevents error 14 "Bad Addr" on Windows (#11933). If the error happens - // the process appears deadlocked - std::thread::sleep(std::time::Duration::from_nanos(1)); // Open the data file let data_file = wopen_cloexec(file_path, locking_mode.file_flags(), LOCKED_FILE_MODE)?; diff --git a/src/history/history.rs b/src/history/history.rs index 1b7ce5f39..7780921a9 100644 --- a/src/history/history.rs +++ b/src/history/history.rs @@ -2015,11 +2015,6 @@ fn pound_on_history(item_count: usize, idx: usize) -> Arc { fn test_history_races() { let _cleanup = test_init(); - // Fail nearly every time on Cygwin (probably caused by flock issue, see #11933) - if cfg!(cygwin) { - return; - } - let tmp_path = std::env::current_dir() .unwrap() .join("history-races-test-balloon");