Fix uvar file mtime force-update (Rust port regression)

When two fish processes rewrite the uvar file concurrent, they rely on the
uvar file's mtime (queried after taking a lock, if locking is supported) to
tell us whether their view of the uvar file is still up-to-date.  If it is,
they proceed to move it into place atomically via rename().

Since the observable mtime only updates on every OS clock tick, we call
futimens() manually to force-update that, to make sure that -- unless both
fish conincide on the same *nanosecond* -- other fish will notice that the
file changed.

Unfortunately, commit 77aeb6a2a8 (Port execution, 2023-10-08) accidentally
made us call futimens() only if clock_gettime() failed, instead of when
it succeeded. This means that we need to wait for the next clock tick to
observe a change in mtime.
Any resulting false negatives might have caused us to drop universal variable updates.

Reported in https://github.com/fish-shell/fish-shell/pull/11492#discussion_r2098948362

See #10300
This commit is contained in:
Johannes Altmanninger
2025-05-22 14:09:16 +02:00
parent 3867163193
commit 8617964d4d

View File

@@ -801,7 +801,7 @@ fn save(&mut self, directory: &wstr) -> bool {
{
let mut times: [libc::timespec; 2] = unsafe { std::mem::zeroed() };
times[0].tv_nsec = libc::UTIME_OMIT; // don't change ctime
if unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut times[1]) } != 0 {
if unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut times[1]) } == 0 {
unsafe {
libc::futimens(private_file.as_raw_fd(), &times[0]);
}