mirror of
https://github.com/RhapsodiOS/RhapsodiOS.git
synced 2026-11-03 22:01:40 -07:00
[GH-ISSUE #75] fifofs: fifo_close leaks the fifoinfo and its two sockets when the last close sees v_usecount > 1 #68
Labels
No labels
bug
documentation
enhancement
enhancement
good first issue
help wanted
help wanted
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
github-starred/RhapsodiOS#68
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @raynorpat on GitHub (Oct 20, 2026).
Original GitHub issue: https://github.com/RhapsodiOS/RhapsodiOS/issues/75
Symptom
A fifo's
struct fifoinfoand its two sockets are never freed if, at the lastclose, something else holds a reference on the vnode that isn't an open (for example a concurrent lookup orstat). Found by the #68 investigation.Cause
fifo_close(bsd/miscfs/fifofs/fifo_vnops.c~443-461) decrementsfi_readers/fi_writers, but it frees the fifoinfo only whenvp->v_usecount <= 1. If a non-open reference makes it> 1, the function returns early andv_fifoinfostays allocated with no readers or writers.fifo_inactiveonly unlocks the vnode.fifo_reclaimisnullop.ffs_fifoop_entries) reclaim throughffs_reclaim, which doesn't know aboutv_fifoinfo.v_unalso goes with the vnode, which is the field #67 tripped over.Fix direction
fi_readers == 0 && fi_writers == 0), not based onv_usecount. Later BSDs do this.VOP_CLOSEwith neither FREAD nor FWRITE) can't leave it behind either, for every filesystem that uses fifofs (ufs/ffs, ext2fs, hfs, nfs specfs/fifo tables).@raynorpat commented on GitHub (Oct 20, 2026):
Fixed by
a9ee24f2b, merged into ffs-perf inf68d4802c.Reproduced on the base kernel (#67 fix, cksum 606865771).
fifoleak.cdoes 1000 rounds of mkfifo, open O_RDWR, close, unlink, while one child loopsstat()and another loopsutimes()on the path.utimesholds a vnode reference while it sleeps in a synchronous inode update, so the last close seesv_usecount > 1.Revoke leaked too: vclean holds its own reference when it calls VOP_CLOSE. It also left threads asleep in
fifo_openforever.Fix:
fifo_releasefrees the fifoinfo once there are no readers, no writers and no sleepers.fi_busycounts threads asleep with the vnode unlocked (infifo_open,fifo_readandfifo_write).fifo_unbusyrelocks the vnode, drops the count and callsfifo_release.v_fifoinfoand wakes every sleeper. The fifoinfo is freed at once or by the last sleeper to leave, so it can't be leaked or freed twice.fifo_openreturns EBADF, and a blocked reader gets EOF.No filesystem changes were needed.
Verified on the fixed kernel (cksum 3755032458):
stress-misc fifobesidestress-net fdpassfor about 40 minutes, 48 fifo and 90 fdpass runs, all PASS.check-misc,check-netandcheck-fspass.soak -t 600 -j 4has no failures. fsck matches the untouched base image.Left open:
fifo_printinfo(reachable only throughvprint) doesn't check for a NULLv_fifoinfo.