[pulseaudio-discuss] [PATCH 5/7] hack around another OS X bug: recv() with MSG_PEEK does not work

Daniel Mack daniel at caiaq.de
Tue Dec 8 18:47:13 PST 2009


At least for pipes, recv() with MSG_PEEK does actually eat up data from
file descriptors. Hence, this can't be used for PULLHUP emulation.

Use another ioctl hack for that.
---
 src/pulsecore/poll.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c
index 27f04aa..cd9aaca 100644
--- a/src/pulsecore/poll.c
+++ b/src/pulsecore/poll.c
@@ -35,6 +35,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif
+
 #include <errno.h>
 
 #ifdef HAVE_SYS_SELECT_H
@@ -66,7 +70,9 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
     struct pollfd *f;
     int ready;
     int maxfd = 0;
+#ifdef OS_IS_WIN32
     char data[64];
+#endif
 
     FD_ZERO (&rset);
     FD_ZERO (&wset);
@@ -109,6 +115,7 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
     ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
                     SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
                     SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
+
     if ((ready == -1) && (errno == EBADF)) {
         ready = 0;
 
@@ -171,6 +178,8 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
 #endif
 
     if (ready > 0) {
+        int r;
+
         ready = 0;
         for (f = fds; f < &fds[nfds]; ++f) {
             f->revents = 0;
@@ -178,6 +187,18 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
                 if (FD_ISSET (f->fd, &rset)) {
                     /* support for POLLHUP.  An hung up descriptor does not
                        increase the return value! */
+#ifdef OS_IS_DARWIN
+                    /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
+                     * for some kinds of descriptors.  Detect if this descriptor is a
+                     * connected socket, a server socket, or something else using a
+                     * 0-byte recv, and use ioctl(2) to detect POLLHUP.  */
+                    r = recv(f->fd, NULL, 0, MSG_PEEK);
+		    if (r == 0 || (r < 0 && errno == ENOTSOCK))
+		        ioctl(f->fd, FIONREAD, &r);
+
+		    if (r == 0)
+		        f->revents |= POLLHUP;
+#else /* !OS_IS_DARWIN */
                     if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
                         if (errno == ESHUTDOWN || errno == ECONNRESET ||
                             errno == ECONNABORTED || errno == ENETRESET) {
@@ -185,6 +206,7 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
                             f->revents |= POLLHUP;
                         }
                     }
+#endif
 
                     if (f->revents == 0)
                         f->revents |= POLLIN;
-- 
1.6.3.3




More information about the pulseaudio-discuss mailing list