Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Jul 2009 09:50:04 GMT
From:      dfilter@FreeBSD.ORG (dfilter service)
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/94772: commit references a PR
Message-ID:  <200907070950.n679o4rt030345@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/94772; it has been noted by GNATS.

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/94772: commit references a PR
Date: Tue,  7 Jul 2009 09:44:00 +0000 (UTC)

 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) \
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907070950.n679o4rt030345>