Merge order: this is 1 of 4 (#23 → #24 → #25 → #26). Each later PR is stacked on the one before it, so until that one is merged its diff also shows the earlier PRs' commits.
FileEditor now releases its lock as soon as it is dropped.
The bug:FileEditor holds an flock. When another thread in the same program starts a child process, the child briefly shares the locked descriptor, until it calls exec. During that window, reopening the file right after dropping the editor was refused with Error::Locked. This is what made edit_interop::editor_locks_the_file fail once in a full parallel test run.
The fix:Drop unlocks the file before closing it, which releases the lock for every descriptor that shares it. The agent store's lock file had the same pattern, previously hidden by its 250 ms retry on open, and gets the same fix.
Before the fix: 1483 of 2000 reopens were refused.
After the fix: none refused, in 30 runs.
Lock type unchanged: an F_OFD_SETLK lock would not help. A forked child inherits it the same way, and on Linux it doesn't conflict with libhdf5's flock, so h5py would no longer be refused. The existing test that h5py is refused still passes.
**Merge order: this is 1 of 4 (#23 → #24 → #25 → #26).** Each later PR is stacked on the one before it, so until that one is merged its diff also shows the earlier PRs' commits.
`FileEditor` now releases its lock as soon as it is dropped.
**The bug:** `FileEditor` holds an `flock`. When another thread in the same program starts a child process, the child briefly shares the locked descriptor, until it calls `exec`. During that window, reopening the file right after dropping the editor was refused with `Error::Locked`. This is what made `edit_interop::editor_locks_the_file` fail once in a full parallel test run.
**The fix:** `Drop` unlocks the file before closing it, which releases the lock for every descriptor that shares it. The agent store's lock file had the same pattern, previously hidden by its 250 ms retry on open, and gets the same fix.
**Reproducer:** `edit_tests::drop_releases_the_lock_while_other_threads_spawn_processes` (tank, 2026-09-28):
- Before the fix: 1483 of 2000 reopens were refused.
- After the fix: none refused, in 30 runs.
**Lock type unchanged:** an `F_OFD_SETLK` lock would not help. A forked child inherits it the same way, and on Linux it doesn't conflict with libhdf5's `flock`, so h5py would no longer be refused. The existing test that h5py is refused still passes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
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]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Merge order: this is 1 of 4 (#23 → #24 → #25 → #26). Each later PR is stacked on the one before it, so until that one is merged its diff also shows the earlier PRs' commits.
FileEditornow releases its lock as soon as it is dropped.The bug:
FileEditorholds anflock. When another thread in the same program starts a child process, the child briefly shares the locked descriptor, until it callsexec. During that window, reopening the file right after dropping the editor was refused withError::Locked. This is what madeedit_interop::editor_locks_the_filefail once in a full parallel test run.The fix:
Dropunlocks the file before closing it, which releases the lock for every descriptor that shares it. The agent store's lock file had the same pattern, previously hidden by its 250 ms retry on open, and gets the same fix.Reproducer:
edit_tests::drop_releases_the_lock_while_other_threads_spawn_processes(tank, 2026-09-28):Lock type unchanged: an
F_OFD_SETLKlock would not help. A forked child inherits it the same way, and on Linux it doesn't conflict with libhdf5'sflock, so h5py would no longer be refused. The existing test that h5py is refused still passes.🤖 Generated with Claude Code