Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 25 Aug 2009 21:44:14 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r196556 - in head/sys: fs/fifofs kern
Message-ID:  <200908252144.n7PLiETE040556@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Tue Aug 25 21:44:14 2009
New Revision: 196556
URL: http://svn.freebsd.org/changeset/base/196556

Log:
  Fix poll() on half-closed sockets, while retaining POLLHUP for fifos.
  
  This reverts part of r196460, so that sockets only return POLLHUP if both
  directions are closed/error. Fifos get POLLHUP by closing the unused
  direction immediately after creating the sockets.
  
  The tools/regression/poll/*poll.c tests now pass except for two other things:
  - if POLLHUP is returned, POLLIN is always returned as well instead of only
    when there is data left in the buffer to be read
  - fifo old/new reader distinction does not work the way POSIX specs it
  
  Reviewed by:	kib, bde

Modified:
  head/sys/fs/fifofs/fifo_vnops.c
  head/sys/kern/uipc_socket.c

Modified: head/sys/fs/fifofs/fifo_vnops.c
==============================================================================
--- head/sys/fs/fifofs/fifo_vnops.c	Tue Aug 25 20:35:57 2009	(r196555)
+++ head/sys/fs/fifofs/fifo_vnops.c	Tue Aug 25 21:44:14 2009	(r196556)
@@ -193,6 +193,9 @@ fifo_open(ap)
 			goto fail2;
 		fip->fi_writesock = wso;
 		error = soconnect2(wso, rso);
+		/* Close the direction we do not use, so we can get POLLHUP. */
+		if (error == 0)
+			error = soshutdown(rso, SHUT_WR);
 		if (error) {
 			(void)soclose(wso);
 fail2:

Modified: head/sys/kern/uipc_socket.c
==============================================================================
--- head/sys/kern/uipc_socket.c	Tue Aug 25 20:35:57 2009	(r196555)
+++ head/sys/kern/uipc_socket.c	Tue Aug 25 21:44:14 2009	(r196556)
@@ -2898,11 +2898,13 @@ 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 |= POLLHUP;
-	if (so->so_snd.sb_state & SBS_CANTSENDMORE)
-		revents |= POLLHUP;
+	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 | POLLPRI | POLLRDNORM | POLLRDBAND)) {



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