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);
}
}