bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Updates to poll module


From: Paolo Bonzini
Subject: Updates to poll module
Date: Wed, 27 Sep 2006 13:19:36 +0200
User-agent: Thunderbird 1.5.0.7 (Macintosh/20060909)

I enclose the promised updates to the poll module in order to work around more braindeadness of the Tiger implementation of poll. recvfrom sometimes ignores MSG_PEEK on some file descriptors, e.g. pipes. We can more or less work around this using FIONREAD instead (on Mac OS X only, since the old way apparently worked great on most systems).

In other words yes, here is the sad truth: there is no way of having POLLHUP detection work reliably on Tiger (it does not work for consoles, for example). This is going to die with Leopard (which they promise will have a reliable implementation of kqueue, and hence poll, for non-socket descriptors too), but my guess that not all Mac users will upgrade...

Ok?

Paolo
2006-09-27  Paolo Bonzini  <address@hidden>

        * m4/poll.m4: Test for sys/ioctl.h and sys/filio.h.
        * lib/poll.c (poll) [__APPLE__]: Use FIONREAD instead of MSG_PEEK.

Index: m4/poll.m4
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/poll.m4,v
retrieving revision 1.7
diff -u -r1.7 poll.m4
--- m4/poll.m4  24 Apr 2006 11:33:54 -0000      1.7
+++ m4/poll.m4  27 Sep 2006 11:15:57 -0000
@@ -68,5 +68,5 @@
 AC_DEFUN([gl_PREREQ_POLL],
 [
   AC_REQUIRE([AC_HEADER_TIME])
-  AC_CHECK_HEADERS_ONCE(sys/time.h)
+  AC_CHECK_HEADERS_ONCE(sys/time.h sys/ioctl.h sys/filio.h)
 ])
Index: lib/poll.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/poll.c,v
retrieving revision 1.4
diff -u -r1.4 poll.c
--- lib/poll.c  19 Sep 2005 17:28:14 -0000      1.4
+++ lib/poll.c  27 Sep 2006 11:15:57 -0000
@@ -1,7 +1,7 @@
 /* Emulation for poll(2)
    Contributed by Paolo Bonzini.
 
-   Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright 2001, 2002, 2003, 2006 Free Software Foundation, Inc.
 
    This file is part of gnulib.
 
@@ -19,9 +19,7 @@
    with this program; if not, write to the Free Software Foundation,
    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include "config.h"
 
 #include <sys/types.h>
 #include "poll.h"
@@ -31,6 +29,13 @@
 #include <sys/select.h>
 #include <unistd.h>
 
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
 #if TIME_WITH_SYS_TIME
 # include <sys/time.h>
 # include <time.h>
@@ -60,7 +65,6 @@
   struct timeval tv, *ptv;
   int maxfd, rc, happened;
   nfds_t i;
-  char data[64];
 
 #ifdef _SC_OPEN_MAX
   if (nfd > sysconf (_SC_OPEN_MAX))
@@ -153,15 +157,40 @@
          happened = 0;
          if (FD_ISSET (pfd[i].fd, &rfds))
            {
-             /* support for POLLHUP.  An hung up descriptor does not
-                increase the return value! */
-             if (recv (pfd[i].fd, data, 64, MSG_PEEK) == -1)
+             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;
+#else
+             char data[64];
+             r = recv (pfd[i].fd, data, 64, MSG_PEEK);
+             if (r == -1)
                {
-                 if (errno == ESHUTDOWN || errno == ECONNRESET
-                     || errno == ECONNABORTED || errno == ENETRESET)
-                   pfd[i].revents |= POLLHUP;
+                 avail = (errno == ESHUTDOWN || errno == ECONNRESET ||
+                          errno == ECONNABORTED || errno == ENETRESET) ? 0 : 
-1;
+                 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;
            }
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]