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