NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
PR/59578 CVS commit: src
The following reply was made to PR kern/59578; it has been noted by GNATS.
From: "Taylor R Campbell" <riastradh%netbsd.org@localhost>
To: gnats-bugs%gnats.NetBSD.org@localhost
Cc:
Subject: PR/59578 CVS commit: src
Date: Tue, 22 Sep 2026 13:34:00 +0000
Module Name: src
Committed By: riastradh
Date: Tue Sep 22 13:34:00 UTC 2026
Modified Files:
src/sys/miscfs/fifofs: fifo_vnops.c
src/tests/lib/libc/sys: t_mkfifo.c
Log Message:
fifo: Fix race between open and signal.
The problem is:
thread A thread B
-------- --------
enter open("fifo", O_WRONLY)
-> fi_writers++
-> sleep since fi_readers == 0
enter open("fifo", O_RDONLY)
-> fi_readers++
-> succeed since fi_writers > 0
open succeeds with fd
enter close(fd)
-> fi_readers--
close succeeds
*SIGALRM*
-> fi_writers--
open fails with EINTR
At this point, a reader open() has succeeded with no corresponding
writer open() success, and if the writer retries, it will hang
because fi_readers is back to zero. Instead, when the reader open()
succeeds, it should cause the writer open() to succeed as well (and
handle the signal afterward).
Solution: create a generation number that is advanced whenever a
reader successfully opens; any writers will succeed on wakeup if the
read generation has advanced since they went to sleep.
thread A thread B
-------- --------
enter open("fifo", O_WRONLY)
-> fi_writers++
-> save rgen = fi_rgen = 0
-> sleep since fi_readers == 0
enter open("fifo", O_RDONLY)
-> fi_readers++
-> succeed since fi_writers > 0
-> fi_rgen++
open succeeds with fd
enter close(fd)
-> fi_readers--
close succeeds
*SIGALRM*
-> succeed since 0 = rgen != fi_rgen = 1
open succeeds with fd
Same problem occurs in with the reader/writer roles reversed; same
solution in the other direction, with a writer generation number.
PR kern/59578: open() hangs indefinitely on FIFO with frequent signal
interruption
Related bugs:
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=203162
https://bugs.python.org/issue25122
https://github.com/python/cpython/issues/137397
Implementation based on FreeBSD rev. 288044 by Konstantin Belousov:
https://svnweb.freebsd.org/base?view=revision&revision=288044
I chose to use uint64_t generation numbers so that we don't have to
think about overflow from counting.
To generate a diff of this commit:
cvs rdiff -u -r1.91 -r1.92 src/sys/miscfs/fifofs/fifo_vnops.c
cvs rdiff -u -r1.5 -r1.6 src/tests/lib/libc/sys/t_mkfifo.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Home |
Main Index |
Thread Index |
Old Index