From owner-svn-src-head@FreeBSD.ORG Tue Jul 7 09:43:45 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0F09C10656CB; Tue, 7 Jul 2009 09:43:45 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E72898FC23; Tue, 7 Jul 2009 09:43:44 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n679hinY008700; Tue, 7 Jul 2009 09:43:44 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n679hin1008696; Tue, 7 Jul 2009 09:43:44 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200907070943.n679hin1008696@svn.freebsd.org> From: Konstantin Belousov Date: Tue, 7 Jul 2009 09:43:44 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195423 - in head/sys: fs/fifofs kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 07 Jul 2009 09:43:45 -0000 Author: kib Date: Tue Jul 7 09:43:44 2009 New Revision: 195423 URL: http://svn.freebsd.org/changeset/base/195423 Log: Fix poll(2) and select(2) for named pipes to return "ready for read" when all writers, observed by reader, exited. Use writer generation counter for fifo, and store the snapshot of the fifo generation in the f_seqcount field of struct file, that is otherwise unused for fifos. Set FreeBSD-undocumented POLLINIGNEOF flag only when file f_seqcount is equal to fifo' fi_wgen, and revert r89376. Fix POLLINIGNEOF for sockets and pipes, and return POLLHUP for them. Note that the patch does not fix not returning POLLHUP for fifos. PR: kern/94772 Submitted by: bde (original version) Reviewed by: rwatson, jilles Approved by: re (kensmith) MFC after: 6 weeks (might be) Modified: head/sys/fs/fifofs/fifo_vnops.c head/sys/kern/sys_pipe.c head/sys/kern/uipc_socket.c head/sys/sys/socketvar.h Modified: head/sys/fs/fifofs/fifo_vnops.c ============================================================================== --- head/sys/fs/fifofs/fifo_vnops.c Tue Jul 7 00:02:26 2009 (r195422) +++ head/sys/fs/fifofs/fifo_vnops.c Tue Jul 7 09:43:44 2009 (r195423) @@ -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, 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) { Modified: head/sys/kern/sys_pipe.c ============================================================================== --- head/sys/kern/sys_pipe.c Tue Jul 7 00:02:26 2009 (r195422) +++ head/sys/kern/sys_pipe.c Tue Jul 7 09:43:44 2009 (r195423) @@ -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)) @@ -1364,10 +1363,14 @@ pipe_poll(fp, events, active_cred, td) (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)) revents |= events & (POLLOUT | POLLWRNORM); - if ((rpipe->pipe_state & PIPE_EOF) || - wpipe->pipe_present != PIPE_ACTIVE || - (wpipe->pipe_state & PIPE_EOF)) - revents |= POLLHUP; + if ((events & POLLINIGNEOF) == 0) { + if (rpipe->pipe_state & PIPE_EOF) { + revents |= (events & (POLLIN | POLLRDNORM)); + if (wpipe->pipe_present != PIPE_ACTIVE || + (wpipe->pipe_state & PIPE_EOF)) + revents |= POLLHUP; + } + } if (revents == 0) { if (events & (POLLIN | POLLRDNORM)) { Modified: head/sys/kern/uipc_socket.c ============================================================================== --- head/sys/kern/uipc_socket.c Tue Jul 7 00:02:26 2009 (r195422) +++ head/sys/kern/uipc_socket.c Tue Jul 7 09:43:44 2009 (r195423) @@ -2885,14 +2885,9 @@ sopoll_generic(struct socket *so, int ev 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,16 @@ sopoll_generic(struct socket *so, int ev 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 & (POLLIN | POLLRDNORM); + if (so->so_snd.sb_state & SBS_CANTSENDMORE) + revents |= 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; } Modified: head/sys/sys/socketvar.h ============================================================================== --- head/sys/sys/socketvar.h Tue Jul 7 00:02:26 2009 (r195422) +++ head/sys/sys/socketvar.h Tue Jul 7 09:43:44 2009 (r195423) @@ -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) \