mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -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