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