diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-12-07 00:40:03 +0100 |
---|---|---|
committer | Daniel Mack <daniel@caiaq.de> | 2009-12-16 16:11:38 +0800 |
commit | 28a73ad1203efc6f6dc33629ce653f45081210fa (patch) | |
tree | 7c066ae1da430c88c9e5c93194da8c6e4292b814 /src/pulsecore/poll.c | |
parent | 17d34462eace417075efa2314999a77e41a3849b (diff) |
hack around another OS X bug: recv() with MSG_PEEK does not work
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.
Diffstat (limited to 'src/pulsecore/poll.c')
-rw-r--r-- | 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 1dcace8b..b98fb169 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 @@ -60,7 +64,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); @@ -103,6 +109,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; @@ -165,6 +172,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; @@ -172,6 +181,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) { @@ -179,6 +200,7 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) { f->revents |= POLLHUP; } } +#endif if (f->revents == 0) f->revents |= POLLIN; |