Source-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: src



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