Le vendredi 22 décembre 2006 à 11:55 +0100, Yoann Vandoorselaere a
écrit :
> Le vendredi 22 décembre 2006 à 11:31 +0100, Paolo Bonzini a écrit :
> > >> and it does not work, e.g., on file descriptors.  Sorry.  :-)
> > > 
> > > Could you please provide more information about the problem? (Note that
> > > the current CVS version doesn't work on socket, which is not much
> > > better). Providing your test case would help.
> > 
> > Just open a file, and poll it.  It should give POLLIN | POLLRDNORM, 
> > while with your patch recv fails with ENOTSOCK.
> 
> I'm currently working out this issue. I'll send a patch in a while.

The patch is attached, I tested regular file polling under both OS X and
Linux.

-- 
Yoann Vandoorselaere | Responsable R&D / CTO | PreludeIDS Technologies
Tel: +33 (0)8 70 70 21 58                  Fax: +33(0)4 78 42 21 58
http://www.prelude-ids.com
Index: lib/poll.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/poll.c,v
retrieving revision 1.5
diff -u -r1.5 poll.c
--- lib/poll.c	28 Sep 2006 19:58:33 -0000	1.5
+++ lib/poll.c	22 Dec 2006 11:40:27 -0000
@@ -28,6 +28,7 @@
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <unistd.h>
+#include <string.h>
 
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -55,6 +56,8 @@
 #define EOVERFLOW EINVAL
 #endif
 
+
+
 int
 poll (pfd, nfd, timeout)
      struct pollfd *pfd;
@@ -158,40 +161,38 @@
 	  if (FD_ISSET (pfd[i].fd, &rfds))
 	    {
 	      int r;
-	      long avail = -1;
-	      /* support for POLLHUP.  */
+
 #if defined __MACH__ && defined __APPLE__
 	      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK for
-		 some kinds of descriptors.  Use FIONREAD to emulate POLLHUP.
-		 It is still not completely POSIX compliant (it does not fully
-		 work on TTYs), but at least it does not delete data!  For other
-		 platforms, we still use MSG_PEEK because it was proved to be
-		 reliable, and I a leery of changing it.  */
-	      do
-		r = ioctl (pfd[i].fd, FIONREAD, &avail);
-	      while (r == -1 && (errno == EAGAIN || errno == EINTR));
-	      if (avail < 0)
-	        avail = 0;
+	         some kinds of descriptors. Use a length of 0. */
+	      r = recv (pfd[i].fd, NULL, 0, MSG_PEEK);
+	      if (r == 0)
+		happened = POLLIN | POLLRDNORM;
 #else
 	      char data[64];
-	      r = recv (pfd[i].fd, data, 64, MSG_PEEK);
-	      if (r == -1)
+	      r = recv (pfd[i].fd, data, sizeof (data), MSG_PEEK);
+	      if (r == 0)
+		happened = POLLHUP;
+#endif
+	      else if (r < 0 && errno == ENOTSOCK) {
+		ioctl(pfd[i].fd, FIONREAD, &r);
+		if (r == 0)
+		  happened = POLLHUP;
+	      }
+
+	      else if (r > 0)
+		happened = POLLIN | POLLRDNORM;
+
+	      else if (r < 0)
 		{
-		  avail = (errno == ESHUTDOWN || errno == ECONNRESET ||
-	                   errno == ECONNABORTED || errno == ENETRESET) ? 0 : -1;
+		  if (errno == ENOTCONN)
+		    happened = POLLIN | POLLRDNORM;	/* Event happening on an unconnected server socket. */
+		  else
+		    happened = (errno == ESHUTDOWN || errno == ECONNRESET ||
+				errno == ECONNABORTED
+				|| errno == ENETRESET) ? POLLHUP : POLLERR;
 		  errno = 0;
 		}
-	      else
-	        avail = r;
-#endif
-
-	      /* An hung up descriptor does not increase the return value! */
-	      if (avail == 0)
-		pfd[i].revents |= POLLHUP;
-	      else if (avail == -1)
-		pfd[i].revents |= POLLERR;
-	      else
-		happened |= POLLIN | POLLRDNORM;
 	    }
 
 	  if (FD_ISSET (pfd[i].fd, &wfds))
@@ -200,7 +201,7 @@
 	  if (FD_ISSET (pfd[i].fd, &efds))
 	    happened |= POLLPRI | POLLRDBAND;
 
-	  pfd[i].revents |= pfd[i].events & happened;
+	  pfd[i].revents |= happened;
 	  rc += (happened > 0);
 	}
     }

Reply via email to