Index: sys/fs/fifofs/fifo_vnops.c =================================================================== --- sys/fs/fifofs/fifo_vnops.c +++ sys/fs/fifofs/fifo_vnops.c @@ -174,8 +174,10 @@ fip->fi_rgen++; if (fip->fi_readers == 1) { fpipe->pipe_state &= ~PIPE_EOF; - if (fip->fi_writers > 0) + if (fip->fi_writers > 0) { wakeup(&fip->fi_writers); + pipeselwakeup(fpipe); + } } fp->f_pipegen = fpipe->pipe_wgen - fip->fi_writers; } @@ -190,8 +192,10 @@ fip->fi_wgen++; if (fip->fi_writers == 1) { fpipe->pipe_state &= ~PIPE_EOF; - if (fip->fi_readers > 0) + if (fip->fi_readers > 0) { wakeup(&fip->fi_readers); + pipeselwakeup(fpipe); + } } } if ((ap->a_mode & O_NONBLOCK) == 0) { @@ -210,6 +214,7 @@ fpipe->pipe_state |= PIPE_EOF; if (fpipe->pipe_state & PIPE_WANTW) wakeup(fpipe); + pipeselwakeup(fpipe); PIPE_UNLOCK(fpipe); fifo_cleanup(vp); } @@ -238,6 +243,7 @@ if (fpipe->pipe_state & PIPE_WANTR) wakeup(fpipe); fpipe->pipe_wgen++; + pipeselwakeup(fpipe); PIPE_UNLOCK(fpipe); fifo_cleanup(vp); } Index: sys/kern/sys_pipe.c =================================================================== --- sys/kern/sys_pipe.c +++ sys/kern/sys_pipe.c @@ -824,7 +824,13 @@ } } - if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) + /* + * Only wake up writers if there was actually something read. + * Otherwise, when calling read(2) at EOF, a spurious wakeup occurs + * that might lead to issues like PR 203366. + */ + if (nread > 0 && + (rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) pipeselwakeup(rpipe); PIPE_UNLOCK(rpipe); @@ -1430,7 +1436,8 @@ if ((events & POLLINIGNEOF) == 0) { if (rpipe->pipe_state & PIPE_EOF) { - revents |= (events & (POLLIN | POLLRDNORM)); + if (fp->f_flag & FREAD) + revents |= (events & (POLLIN | POLLRDNORM)); if (wpipe->pipe_present != PIPE_ACTIVE || (wpipe->pipe_state & PIPE_EOF)) revents |= POLLHUP; @@ -1605,8 +1612,6 @@ pipelock(cpipe, 0); pp = cpipe->pipe_pair; - pipeselwakeup(cpipe); - /* * If the other side is blocked, wake it up saying that * we want to close it down. @@ -1620,16 +1625,16 @@ pipelock(cpipe, 0); } + pipeselwakeup(cpipe); + /* * Disconnect from peer, if any. */ ppipe = cpipe->pipe_peer; if (ppipe->pipe_present == PIPE_ACTIVE) { - pipeselwakeup(ppipe); - ppipe->pipe_state |= PIPE_EOF; wakeup(ppipe); - KNOTE_LOCKED(&ppipe->pipe_sel.si_note, 0); + pipeselwakeup(ppipe); } /* @@ -1727,23 +1732,22 @@ static int filt_piperead(struct knote *kn, long hint) { + struct file *fp = kn->kn_fp; struct pipe *rpipe = kn->kn_hook; - struct pipe *wpipe = rpipe->pipe_peer; - int ret; PIPE_LOCK_ASSERT(rpipe, MA_OWNED); kn->kn_data = rpipe->pipe_buffer.cnt; if (kn->kn_data == 0) kn->kn_data = rpipe->pipe_map.cnt; - if ((rpipe->pipe_state & PIPE_EOF) || - wpipe->pipe_present != PIPE_ACTIVE || - (wpipe->pipe_state & PIPE_EOF)) { + if ((rpipe->pipe_state & PIPE_EOF) && + !((rpipe->pipe_state & PIPE_NAMED) && + (fp->f_seqcount == rpipe->pipe_wgen))) { kn->kn_flags |= EV_EOF; return (1); } - ret = kn->kn_data > 0; - return ret; + kn->kn_flags &= ~EV_EOF; + return (kn->kn_data > 0); } /*ARGSUSED*/ @@ -1757,18 +1761,25 @@ * knlist and the list lock (i.e., the pipe lock) is therefore not held. */ wpipe = kn->kn_hook; + + if (wpipe->pipe_present == PIPE_ACTIVE) { + PIPE_LOCK_ASSERT(wpipe, MA_OWNED); + } + + if (wpipe->pipe_state & PIPE_DIRECTW) { + kn->kn_data = 0; + } else if (wpipe->pipe_buffer.size > 0) { + kn->kn_data = wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt; + } else { + kn->kn_data = PIPE_BUF; + } + if (wpipe->pipe_present != PIPE_ACTIVE || (wpipe->pipe_state & PIPE_EOF)) { - kn->kn_data = 0; kn->kn_flags |= EV_EOF; return (1); } - PIPE_LOCK_ASSERT(wpipe, MA_OWNED); - kn->kn_data = (wpipe->pipe_buffer.size > 0) ? - (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) : PIPE_BUF; - if (wpipe->pipe_state & PIPE_DIRECTW) - kn->kn_data = 0; - + kn->kn_flags &= ~EV_EOF; return (kn->kn_data >= PIPE_BUF); }