Browse Source

Merge pull request #22327 from Faless/defective_by_design_is_the_windows_way

Use select instead of WSAPoll on Windows.
Fabio Alessandrelli 7 years ago
parent
commit
5a03d50921
1 changed files with 52 additions and 4 deletions
  1. 52 4
      drivers/unix/net_socket_posix.cpp

+ 52 - 4
drivers/unix/net_socket_posix.cpp

@@ -68,7 +68,6 @@
 #define SOCK_BUF(x) x
 #define SOCK_BUF(x) x
 #define SOCK_CBUF(x) x
 #define SOCK_CBUF(x) x
 #define SOCK_IOCTL ioctl
 #define SOCK_IOCTL ioctl
-#define SOCK_POLL ::poll
 #define SOCK_CLOSE ::close
 #define SOCK_CLOSE ::close
 
 
 /* Windows */
 /* Windows */
@@ -80,7 +79,6 @@
 #define SOCK_BUF(x) (char *)(x)
 #define SOCK_BUF(x) (char *)(x)
 #define SOCK_CBUF(x) (const char *)(x)
 #define SOCK_CBUF(x) (const char *)(x)
 #define SOCK_IOCTL ioctlsocket
 #define SOCK_IOCTL ioctlsocket
-#define SOCK_POLL WSAPoll
 #define SOCK_CLOSE closesocket
 #define SOCK_CLOSE closesocket
 
 
 // Windows doesn't have this flag
 // Windows doesn't have this flag
@@ -331,10 +329,58 @@ Error NetSocketPosix::connect_to_host(IP_Address p_host, uint16_t p_port) {
 	return OK;
 	return OK;
 }
 }
 
 
-Error NetSocketPosix::poll(PollType p_type, int timeout) const {
+Error NetSocketPosix::poll(PollType p_type, int p_timeout) const {
 
 
 	ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
 	ERR_FAIL_COND_V(!is_open(), ERR_UNCONFIGURED);
 
 
+#if defined(WINDOWS_ENABLED)
+	bool ready = false;
+	fd_set rd, wr, ex;
+	fd_set *rdp = NULL;
+	fd_set *wrp = NULL;
+	FD_ZERO(&rd);
+	FD_ZERO(&wr);
+	FD_ZERO(&ex);
+	FD_SET(_sock, &ex);
+	struct timeval timeout = { p_timeout, 0 };
+	// For blocking operation, pass NULL timeout pointer to select.
+	struct timeval *tp = NULL;
+	if (p_timeout >= 0) {
+		//  If timeout is non-negative, we want to specify the timeout instead.
+		tp = &timeout;
+	}
+
+	switch (p_type) {
+		case POLL_TYPE_IN:
+			FD_SET(_sock, &rd);
+			rdp = &rd;
+			break;
+		case POLL_TYPE_OUT:
+			FD_SET(_sock, &wr);
+			wrp = ≀
+			break;
+		case POLL_TYPE_IN_OUT:
+			FD_SET(_sock, &rd);
+			FD_SET(_sock, &wr);
+			rdp = &rd;
+			wrp = ≀
+	}
+	int ret = select(1, rdp, wrp, &ex, tp);
+
+	ERR_FAIL_COND_V(ret == SOCKET_ERROR, FAILED);
+
+	if (ret == 0)
+		return ERR_BUSY;
+
+	ERR_FAIL_COND_V(FD_ISSET(_sock, &ex), FAILED);
+
+	if (rdp && FD_ISSET(_sock, rdp))
+		ready = true;
+	if (wrp && FD_ISSET(_sock, wrp))
+		ready = true;
+
+	return ready ? OK : ERR_BUSY;
+#else
 	struct pollfd pfd;
 	struct pollfd pfd;
 	pfd.fd = _sock;
 	pfd.fd = _sock;
 	pfd.events = POLLIN;
 	pfd.events = POLLIN;
@@ -351,14 +397,16 @@ Error NetSocketPosix::poll(PollType p_type, int timeout) const {
 			pfd.events = POLLOUT || POLLIN;
 			pfd.events = POLLOUT || POLLIN;
 	}
 	}
 
 
-	int ret = SOCK_POLL(&pfd, 1, timeout);
+	int ret = ::poll(&pfd, 1, p_timeout);
 
 
 	ERR_FAIL_COND_V(ret < 0, FAILED);
 	ERR_FAIL_COND_V(ret < 0, FAILED);
+	ERR_FAIL_COND_V(pfd.revents & POLLERR, FAILED);
 
 
 	if (ret == 0)
 	if (ret == 0)
 		return ERR_BUSY;
 		return ERR_BUSY;
 
 
 	return OK;
 	return OK;
+#endif
 }
 }
 
 
 Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {
 Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {