summaryrefslogtreecommitdiffstats
path: root/src/pulsecore
diff options
context:
space:
mode:
authorDaniel Mack <daniel@caiaq.de>2009-12-07 00:40:03 +0100
committerDaniel Mack <daniel@caiaq.de>2009-12-16 16:11:38 +0800
commit28a73ad1203efc6f6dc33629ce653f45081210fa (patch)
tree7c066ae1da430c88c9e5c93194da8c6e4292b814 /src/pulsecore
parent17d34462eace417075efa2314999a77e41a3849b (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')
-rw-r--r--src/pulsecore/poll.c22
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;