clawhdf5: a dropped FileEditor releases its lock at once
CI / test-arm64 (pull_request) Successful in 1m38s
CI / test (pull_request) Successful in 28m11s

FileEditor's flock belongs to the open file description. When another
thread forks to spawn a process, the child shares the locked descriptor
until it execs, so a reopen right after the drop could be refused with
Error::Locked (a one-off failure of edit_interop::editor_locks_the_file in
a parallel test run). Drop now unlocks before closing, which releases the
lock for every descriptor sharing it.

Reproducer edit_tests::drop_releases_the_lock_while_other_threads_spawn_processes
(4 threads running `true`, 2000 open/drop rounds): 1483 of 2000 reopens
refused before, 0 in 30 runs after (tank). An OFD lock would not help: it
is inherited across fork the same way and does not conflict with
libhdf5's flock. The agent store's lock file unlocks on drop too.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-28 21:05:17 -05:00
co-authored by Claude Opus 5.5
parent 5eae9ee60b
commit 3eca5d8334
5 changed files with 116 additions and 2 deletions
+29
View File
@@ -448,6 +448,35 @@ Newest first. "Before any release" means no tagged release (v2.7.0 and
earlier) contains the bug. Full detail is in `CHANGELOG.md` under the date
given.
## A dropped `FileEditor` could keep its file locked for a moment
**Status:** fixed 2026-09-28 (`fix/editor-lock-fork-race`), before any release
(`FileEditor` dates from 2026-09-26). Spurious `Error::Locked` only; no
data was affected. Nothing for users to do.
`FileEditor` locks its file with `flock`, which belongs to the open file
description and lasts until every descriptor of it is closed. When another
thread of the program forked to spawn a process (any
`std::process::Command`), the child inherited the descriptor and kept it
until it exec'd (close-on-exec acts only at `exec`), so an `open` of the
same file right after the editor was dropped could be refused with
`Error::Locked`. It showed up as a one-off failure of
`edit_interop::editor_locks_the_file` in a full parallel `cargo test`;
the deliberate reproducer
(`edit_tests::drop_releases_the_lock_while_other_threads_spawn_processes`:
four threads running `true` in a loop while the main thread opens and drops
an editor 2000 times) had 1483 of 2000 reopens refused on tank. The drop
now unlocks the file explicitly before closing it, which releases the lock
for every descriptor of the description: 0 refused in 30 runs of the same
test. The agent store's `<store>.h5.lock` (`HDF5Memory`, since v2.3.0)
had the same pattern, hidden by its 250 ms retry on open; it unlocks on
drop too.
An `fcntl` open-file-description lock (`F_OFD_SETLK`) would not have
helped: it is inherited across `fork` the same way, and on Linux it does
not conflict with `flock`, so libhdf5 (h5py), which locks with `flock`,
would no longer be refused while an editor holds the file.
## `ObjectHeader::parse` 4% slower after range-read M2/M3
**Status:** fixed 2026-09-27 (`96086ad`, PR #21), before any release.