Skip to content

🐛 fix(soft_rw): evict non-regular write marker without reading it#588

Merged
gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-fifo-marker-eviction-587
Jul 7, 2026
Merged

🐛 fix(soft_rw): evict non-regular write marker without reading it#588
gaborbernat merged 1 commit into
tox-dev:mainfrom
gaborbernat:fix-fifo-marker-eviction-587

Conversation

@gaborbernat

@gaborbernat gaborbernat commented Jul 7, 2026

Copy link
Copy Markdown
Member

Acquiring a SoftReadWriteLock hangs until it times out on FreeBSD when a stale FIFO sits at the .write marker path. _read_marker opens the marker with O_NONBLOCK and reads it to decide whether it is valid, but a non-blocking read of a FIFO returns zero bytes on Linux and macOS while it raises EAGAIN on FreeBSD. 🐛 On the EAGAIN path _read_marker returns None, so _break_stale_marker treats the marker as already gone, leaves it in place, and the writer-slot claim spins until Timeout.

A legitimate marker is a regular file, created with O_CREAT | O_EXCL | O_WRONLY, so the fix checks the file type with fstat and reports anything else as a malformed marker without reading it, letting its mtime drive stale eviction instead of content whose read behavior varies by platform. fstat classifies the FIFO by its inode type rather than by a platform-specific read, so both the writerless marker FreeBSD tripped on and a writer-attached marker that raises EAGAIN get evicted.

Linux and macOS keep their current behavior, since a stale FIFO already resolved to a malformed marker on those platforms. Fixes #587.

@gaborbernat gaborbernat changed the title soft_rw: evict a non-regular write marker without reading it 🐛 fix(soft_rw): evict non-regular write marker without reading it Jul 7, 2026
@gaborbernat gaborbernat added the bug label Jul 7, 2026
@gaborbernat gaborbernat enabled auto-merge (squash) July 7, 2026 17:09
@gaborbernat gaborbernat force-pushed the fix-fifo-marker-eviction-587 branch from afc5d05 to 358cb26 Compare July 7, 2026 17:10
_read_marker read the marker to judge it, but reading a FIFO diverges by
platform: an empty non-blocking read yields 0 bytes on Linux/macOS (so
the FIFO parses as a malformed marker and gets evicted) but raises EAGAIN
on FreeBSD, where _read_marker then returned None, _break_stale_marker
bailed, and the stale FIFO wedged the acquire until timeout (tox-dev#587).

A legitimate marker is always a regular file, so fstat the fd and report
anything else as a malformed marker straight away -- its mtime still
drives stale eviction -- instead of reading it. fstat classifies the FIFO
the same on every platform, so the writerless case FreeBSD tripped on and
the writer-attached case that raises EAGAIN everywhere both evict.

Add test_fifo_write_marker_with_writer_is_evicted: attaching a writer
forces the EAGAIN path on any platform, reproducing the FreeBSD failure
portably. It times out at the same _wait_for line before the fix.
@gaborbernat gaborbernat force-pushed the fix-fifo-marker-eviction-587 branch from 358cb26 to 7f2318a Compare July 7, 2026 18:42
@gaborbernat gaborbernat merged commit 3547d58 into tox-dev:main Jul 7, 2026
33 checks passed
@gaborbernat gaborbernat deleted the fix-fifo-marker-eviction-587 branch July 10, 2026 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The test test_fifo_write_marker_does_no0 fails

1 participant