event ports are broken with FIFOs
fifofs provides two modes of operation - fastpath mode and streams mode. Fastpath implements a subset of fifo functionality while the streams mode implements the full functionality. If an unimplemented fastpath feature is called (e.g., via an ioctl) the fifo is convert to a streams mode and the operation is serviced by the streams mode code. By default, all fifos start in fastpath mode. Once a fifo is in streams mode, it will never switch to the fastpath mode.
Unfortunately, the conversion from fastpath mode to streams mode causes all waiters on events to wake up in the hope that they re-register with the now-in-streams-mode fifo (http://src.illumos.org/source/xref/illumos-gate/usr/src/uts/common/fs/fifofs/fifosubr.c#1108). The application sees a spurious wakeup without a way to know that the wakeup was spurious. If the fifo fd is blocking, the application will get blocked trying to read/write. (Note that the event port man pages do not document anything related to spurious wakeups and therefore application developers are likely to assume that they will not occur.) This was observed with a
getpeerucred in #6474. There the kernel stack leading up to the wakeup was:
genunix`port_send_event+0x131 genunix`pollwakeup+0x86 genunix`strpollwakeup+0x20 fifofs`fifo_fastturnoff+0xae fifofs`fifo_fastoff+0x92 fifofs`fifo_fastioctl+0x19d fifofs`fifo_ioctl+0x3d genunix`fop_ioctl+0x55 genunix`getpeerucred+0xff genunix`ucredsys+0x52 genunix`ucredsys32+0x1b unix`sys_syscall32+0xff
While #6474 fixes the
getpeerucred induced problem there are many other reasons a fifo would get converted. This bug report is intended to track the overarching issue with conversion-induced wakeups.