From 5ccd15517787ba273623cc1c1d7333f758ad2ee9 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Tue, 20 May 2025 15:21:00 +0200 Subject: [PATCH] Retry history file flock() on EINTR When locking the uvar file, we retry whenever flock() fails with EINTR (e.g. due to ctrl-c). But not when locking the history file. This seems wrong; all other libc functions in the "history_file" code path do retry. Fix that. In future we should extract a function. Note that there are other inconsistencies; flock_uvar_file() does not shy away from remote file systems and does not respect ABANDONED_LOCKING. This means that empirically probably neither are necessary; let's make things consistent in future. See https://github.com/fish-shell/fish-shell/pull/11492#discussion_r2095096200 Might help #10300 (cherry picked from commit 4d84e68dd4f8d4c15a36b8d91c6562b8e93ecdee) --- src/history.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/history.rs b/src/history.rs index 565c83f53..1c6e9747a 100644 --- a/src/history.rs +++ b/src/history.rs @@ -44,7 +44,7 @@ }; use bitflags::bitflags; -use libc::{fchmod, fchown, flock, LOCK_EX, LOCK_SH, LOCK_UN}; +use libc::{fchmod, fchown, flock, EINTR, LOCK_EX, LOCK_SH, LOCK_UN}; use lru::LruCache; use nix::{fcntl::OFlag, sys::stat::Mode}; use rand::Rng; @@ -1353,8 +1353,15 @@ unsafe fn maybe_lock_file(file: &mut File, lock_type: libc::c_int) -> bool { return false; } - let start_time = SystemTime::now(); - let retval = unsafe { flock(raw_fd, lock_type) }; + let (ok, start_time) = loop { + let start_time = SystemTime::now(); + if unsafe { flock(raw_fd, lock_type) } == -1 { + if errno::errno().0 != EINTR { + break (false, start_time); + } + } + break (true, start_time); + }; if let Ok(duration) = start_time.elapsed() { if duration > Duration::from_millis(250) { FLOG!( @@ -1367,7 +1374,7 @@ unsafe fn maybe_lock_file(file: &mut File, lock_type: libc::c_int) -> bool { ABANDONED_LOCKING.store(true); } } - retval != -1 + ok } /// Unlock a history file.