mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-08 13:29:59 -05:00
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.
This commit is contained in:
parent
17d34462ea
commit
28a73ad120
1 changed files with 22 additions and 0 deletions
|
|
@ -35,6 +35,10 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYS_SELECT_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;
|
struct pollfd *f;
|
||||||
int ready;
|
int ready;
|
||||||
int maxfd = 0;
|
int maxfd = 0;
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
char data[64];
|
char data[64];
|
||||||
|
#endif
|
||||||
|
|
||||||
FD_ZERO (&rset);
|
FD_ZERO (&rset);
|
||||||
FD_ZERO (&wset);
|
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,
|
ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
|
||||||
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
|
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
|
||||||
SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
|
SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
|
||||||
|
|
||||||
if ((ready == -1) && (errno == EBADF)) {
|
if ((ready == -1) && (errno == EBADF)) {
|
||||||
ready = 0;
|
ready = 0;
|
||||||
|
|
||||||
|
|
@ -165,6 +172,8 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ready > 0) {
|
if (ready > 0) {
|
||||||
|
int r;
|
||||||
|
|
||||||
ready = 0;
|
ready = 0;
|
||||||
for (f = fds; f < &fds[nfds]; ++f) {
|
for (f = fds; f < &fds[nfds]; ++f) {
|
||||||
f->revents = 0;
|
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)) {
|
if (FD_ISSET (f->fd, &rset)) {
|
||||||
/* support for POLLHUP. An hung up descriptor does not
|
/* support for POLLHUP. An hung up descriptor does not
|
||||||
increase the return value! */
|
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 (recv (f->fd, data, 64, MSG_PEEK) == -1) {
|
||||||
if (errno == ESHUTDOWN || errno == ECONNRESET ||
|
if (errno == ESHUTDOWN || errno == ECONNRESET ||
|
||||||
errno == ECONNABORTED || errno == ENETRESET) {
|
errno == ECONNABORTED || errno == ENETRESET) {
|
||||||
|
|
@ -179,6 +200,7 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
|
||||||
f->revents |= POLLHUP;
|
f->revents |= POLLHUP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (f->revents == 0)
|
if (f->revents == 0)
|
||||||
f->revents |= POLLIN;
|
f->revents |= POLLIN;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue