diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index d328f3b..25436c7 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -84,6 +84,7 @@ struct fifoinfo { struct socket *fi_writesock; long fi_readers; long fi_writers; + int fi_wgen; }; static vop_print_t fifo_print; @@ -232,6 +233,7 @@ fail1: sowwakeup(fip->fi_writesock); } } + fp->f_seqcount = fip->fi_wgen - fip->fi_writers; } if (ap->a_mode & FWRITE) { if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { @@ -279,6 +281,9 @@ fail1: fip->fi_writers--; if (fip->fi_writers == 0) { socantrcvmore(fip->fi_readsock); + mtx_lock(&fifo_mtx); + fip->fi_wgen++; + mtx_unlock(&fifo_mtx); fifo_cleanup(vp); } return (error); @@ -395,8 +400,12 @@ fifo_close(ap) } if (ap->a_fflag & FWRITE) { fip->fi_writers--; - if (fip->fi_writers == 0) + if (fip->fi_writers == 0) { socantrcvmore(fip->fi_readsock); + mtx_lock(&fifo_mtx); + fip->fi_wgen++; + mtx_unlock(&fifo_mtx); + } } fifo_cleanup(vp); return (0); @@ -634,28 +643,13 @@ fifo_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td) levents = events & (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND); if ((fp->f_flag & FREAD) && levents) { - /* - * If POLLIN or POLLRDNORM is requested and POLLINIGNEOF is - * not, then convert the first two to the last one. This - * tells the socket poll function to ignore EOF so that we - * block if there is no writer (and no data). Callers can - * set POLLINIGNEOF to get non-blocking behavior. - */ - if (levents & (POLLIN | POLLRDNORM) && - !(levents & POLLINIGNEOF)) { - levents &= ~(POLLIN | POLLRDNORM); - levents |= POLLINIGNEOF; - } - filetmp.f_data = fip->fi_readsock; filetmp.f_cred = cred; + mtx_lock(&fifo_mtx); + if (fp->f_seqcount == fip->fi_wgen) + levents |= POLLINIGNEOF; + mtx_unlock(&fifo_mtx); revents |= soo_poll(&filetmp, levents, cred, td); - - /* Reverse the above conversion. */ - if ((revents & POLLINIGNEOF) && !(events & POLLINIGNEOF)) { - revents |= (events & (POLLIN | POLLRDNORM)); - revents &= ~POLLINIGNEOF; - } } levents = events & (POLLOUT | POLLWRNORM | POLLWRBAND); if ((fp->f_flag & FWRITE) && levents) { diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 45dc0f6..b158b4a 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1353,8 +1353,7 @@ pipe_poll(fp, events, active_cred, td) #endif if (events & (POLLIN | POLLRDNORM)) if ((rpipe->pipe_state & PIPE_DIRECTW) || - (rpipe->pipe_buffer.cnt > 0) || - (rpipe->pipe_state & PIPE_EOF)) + (rpipe->pipe_buffer.cnt > 0)) revents |= events & (POLLIN | POLLRDNORM); if (events & (POLLOUT | POLLWRNORM)) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ecb1b7b..9948a6e 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2885,14 +2885,9 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, SOCKBUF_LOCK(&so->so_snd); SOCKBUF_LOCK(&so->so_rcv); if (events & (POLLIN | POLLRDNORM)) - if (soreadable(so)) + if (soreadabledata(so)) revents |= events & (POLLIN | POLLRDNORM); - if (events & POLLINIGNEOF) - if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat || - !TAILQ_EMPTY(&so->so_comp) || so->so_error) - revents |= POLLINIGNEOF; - if (events & (POLLOUT | POLLWRNORM)) if (sowriteable(so)) revents |= events & (POLLOUT | POLLWRNORM); @@ -2901,10 +2896,14 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK)) revents |= events & (POLLPRI | POLLRDBAND); + if ((events & POLLINIGNEOF) == 0) + if (so->so_rcv.sb_state & SBS_CANTRCVMORE) + revents |= events & (POLLHUP | POLLIN); + if (so->so_snd.sb_state & SBS_CANTSENDMORE) + revents |= events & POLLHUP; + if (revents == 0) { - if (events & - (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | - POLLRDBAND)) { + if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { selrecord(td, &so->so_rcv.sb_sel); so->so_rcv.sb_flags |= SB_SEL; } diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 2817b84..8899083 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -197,10 +197,11 @@ struct xsocket { ((so)->so_proto->pr_flags & PR_ATOMIC) /* can we read something from so? */ -#define soreadable(so) \ +#define soreadabledata(so) \ ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \ - ((so)->so_rcv.sb_state & SBS_CANTRCVMORE) || \ !TAILQ_EMPTY(&(so)->so_comp) || (so)->so_error) +#define soreadable(so) \ + (soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE)) /* can we write something to so? */ #define sowriteable(so) \