Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Aug 2010 17:42:08 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r211941 - head/sys/kern
Message-ID:  <201008281742.o7SHg8gZ038628@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Aug 28 17:42:08 2010
New Revision: 211941
URL: http://svn.freebsd.org/changeset/base/211941

Log:
  For some file types, select code registers two selfd structures. E.g.,
  for socket, when specified POLLIN|POLLOUT in events, you would have one
  selfd registered for receiving socket buffer, and one for sending. Now,
  if both events are not ready to fire at the time of the initial scan,
  but are simultaneously ready after the sleep, pollrescan() would iterate
  over the pollfd struct twice. Since both times revents is not zero,
  returned value would be off by one.
  
  Fix this by recalculating the return value in pollout().
  
  PR:	kern/143029
  MFC after:	2 weeks

Modified:
  head/sys/kern/sys_generic.c

Modified: head/sys/kern/sys_generic.c
==============================================================================
--- head/sys/kern/sys_generic.c	Sat Aug 28 17:38:40 2010	(r211940)
+++ head/sys/kern/sys_generic.c	Sat Aug 28 17:42:08 2010	(r211941)
@@ -76,7 +76,8 @@ static MALLOC_DEFINE(M_IOCTLOPS, "ioctlo
 static MALLOC_DEFINE(M_SELECT, "select", "select() buffer");
 MALLOC_DEFINE(M_IOV, "iov", "large iov's");
 
-static int	pollout(struct pollfd *, struct pollfd *, u_int);
+static int	pollout(struct thread *, struct pollfd *, struct pollfd *,
+		    u_int);
 static int	pollscan(struct thread *, struct pollfd *, u_int);
 static int	pollrescan(struct thread *);
 static int	selscan(struct thread *, fd_mask **, fd_mask **, int);
@@ -1207,7 +1208,7 @@ done:
 	if (error == EWOULDBLOCK)
 		error = 0;
 	if (error == 0) {
-		error = pollout(bits, uap->fds, nfds);
+		error = pollout(td, bits, uap->fds, nfds);
 		if (error)
 			goto out;
 	}
@@ -1262,22 +1263,27 @@ pollrescan(struct thread *td)
 
 
 static int
-pollout(fds, ufds, nfd)
+pollout(td, fds, ufds, nfd)
+	struct thread *td;
 	struct pollfd *fds;
 	struct pollfd *ufds;
 	u_int nfd;
 {
 	int error = 0;
 	u_int i = 0;
+	u_int n = 0;
 
 	for (i = 0; i < nfd; i++) {
 		error = copyout(&fds->revents, &ufds->revents,
 		    sizeof(ufds->revents));
 		if (error)
 			return (error);
+		if (fds->revents != 0)
+			n++;
 		fds++;
 		ufds++;
 	}
+	td->td_retval[0] = n;
 	return (0);
 }
 



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