mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
core: make sure win32 sockets remain blocking
Commit 7e344b5 hade the side effect of forcing every socket to
be non-blocking on Windows. This is because of a (documented)
side effect of WSAEventSelect(). So we need to make sure to restore
blocking behaviour afterwards for relevant sockets.
This commit is contained in:
parent
abfca5cb58
commit
0138a51a2c
3 changed files with 69 additions and 9 deletions
|
|
@ -148,6 +148,10 @@
|
||||||
|
|
||||||
static pa_strlist *recorded_env = NULL;
|
static pa_strlist *recorded_env = NULL;
|
||||||
|
|
||||||
|
#ifdef OS_IS_WIN32
|
||||||
|
static fd_set nonblocking_fds;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef OS_IS_WIN32
|
#ifdef OS_IS_WIN32
|
||||||
|
|
||||||
#include "poll.h"
|
#include "poll.h"
|
||||||
|
|
@ -179,8 +183,59 @@ char *pa_win32_get_toplevel(HANDLE handle) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void set_nonblock(int fd, bool nonblock) {
|
||||||
|
|
||||||
|
#ifdef O_NONBLOCK
|
||||||
|
int v, nv;
|
||||||
|
pa_assert(fd >= 0);
|
||||||
|
|
||||||
|
pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
|
||||||
|
|
||||||
|
if (nonblock)
|
||||||
|
nv = v | O_NONBLOCK;
|
||||||
|
else
|
||||||
|
nv = v & ~O_NONBLOCK;
|
||||||
|
|
||||||
|
if (v != nv)
|
||||||
|
pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
|
||||||
|
|
||||||
|
#elif defined(OS_IS_WIN32)
|
||||||
|
u_long arg;
|
||||||
|
|
||||||
|
if (nonblock)
|
||||||
|
arg = 1;
|
||||||
|
else
|
||||||
|
arg = 0;
|
||||||
|
|
||||||
|
if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
|
||||||
|
pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
|
||||||
|
pa_log_warn("Only sockets can be made non-blocking!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There is no method to query status, so we remember all fds */
|
||||||
|
if (nonblock)
|
||||||
|
FD_SET(fd, &nonblocking_fds);
|
||||||
|
else
|
||||||
|
FD_CLR(fd, &nonblocking_fds);
|
||||||
|
#else
|
||||||
|
pa_log_warn("Non-blocking I/O not supported.!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/** Make a file descriptor nonblock. Doesn't do any error checking */
|
/** Make a file descriptor nonblock. Doesn't do any error checking */
|
||||||
void pa_make_fd_nonblock(int fd) {
|
void pa_make_fd_nonblock(int fd) {
|
||||||
|
set_nonblock(fd, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Make a file descriptor blocking. Doesn't do any error checking */
|
||||||
|
void pa_make_fd_block(int fd) {
|
||||||
|
set_nonblock(fd, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query if a file descriptor is non-blocking */
|
||||||
|
bool pa_is_fd_nonblock(int fd) {
|
||||||
|
|
||||||
#ifdef O_NONBLOCK
|
#ifdef O_NONBLOCK
|
||||||
int v;
|
int v;
|
||||||
|
|
@ -188,17 +243,12 @@ void pa_make_fd_nonblock(int fd) {
|
||||||
|
|
||||||
pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
|
pa_assert_se((v = fcntl(fd, F_GETFL)) >= 0);
|
||||||
|
|
||||||
if (!(v & O_NONBLOCK))
|
return !!(v & O_NONBLOCK);
|
||||||
pa_assert_se(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0);
|
|
||||||
|
|
||||||
#elif defined(OS_IS_WIN32)
|
#elif defined(OS_IS_WIN32)
|
||||||
u_long arg = 1;
|
return !!FD_ISSET(fd, &nonblocking_fds);
|
||||||
if (ioctlsocket(fd, FIONBIO, &arg) < 0) {
|
|
||||||
pa_assert_se(WSAGetLastError() == WSAENOTSOCK);
|
|
||||||
pa_log_warn("Only sockets can be made non-blocking!");
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
pa_log_warn("Non-blocking I/O not supported.!");
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -531,13 +581,15 @@ ssize_t pa_loop_write(int fd, const void*data, size_t size, int *type) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Platform independent read function. Necessary since not all
|
/** Platform independent close function. Necessary since not all
|
||||||
* systems treat all file descriptors equal. */
|
* systems treat all file descriptors equal. */
|
||||||
int pa_close(int fd) {
|
int pa_close(int fd) {
|
||||||
|
|
||||||
#ifdef OS_IS_WIN32
|
#ifdef OS_IS_WIN32
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
FD_CLR(fd, &nonblocking_fds);
|
||||||
|
|
||||||
if ((ret = closesocket(fd)) == 0)
|
if ((ret = closesocket(fd)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,9 @@ struct timeval;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void pa_make_fd_nonblock(int fd);
|
void pa_make_fd_nonblock(int fd);
|
||||||
|
void pa_make_fd_block(int fd);
|
||||||
|
bool pa_is_fd_nonblock(int fd);
|
||||||
|
|
||||||
void pa_make_fd_cloexec(int fd);
|
void pa_make_fd_cloexec(int fd);
|
||||||
|
|
||||||
int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid, bool update_perms);
|
int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid, bool update_perms);
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ typedef unsigned long nfds_t;
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <pulsecore/core-util.h>
|
||||||
|
|
||||||
#ifndef INFTIM
|
#ifndef INFTIM
|
||||||
# define INFTIM (-1)
|
# define INFTIM (-1)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -602,6 +604,9 @@ restart:
|
||||||
/* It's a socket. */
|
/* It's a socket. */
|
||||||
WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
|
WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
|
||||||
WSAEventSelect ((SOCKET) h, 0, 0);
|
WSAEventSelect ((SOCKET) h, 0, 0);
|
||||||
|
/* Have to restore blocking as WSAEventSelect() clears it */
|
||||||
|
if (!pa_is_fd_nonblock(pfd[i].fd))
|
||||||
|
pa_make_fd_block(pfd[i].fd);
|
||||||
|
|
||||||
/* If we're lucky, WSAEnumNetworkEvents already provided a way
|
/* If we're lucky, WSAEnumNetworkEvents already provided a way
|
||||||
to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
|
to distinguish FD_READ and FD_ACCEPT; this saves a recv later. */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue