Use select instead of WSAPoll on Windows.
WSAPoll is broken by design. It was announced as the new way to introduce compatibility to posix sockets, their implementation was broken, and they decided not to fix it. You can read the full story here: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
This commit is contained in:
parent
ef7b384861
commit
a15db2d2b6
|
@ -68,7 +68,6 @@
|
|||
#define SOCK_BUF(x) x
|
||||
#define SOCK_CBUF(x) x
|
||||
#define SOCK_IOCTL ioctl
|
||||
#define SOCK_POLL ::poll
|
||||
#define SOCK_CLOSE ::close
|
||||
|
||||
/* Windows */
|
||||
|
@ -80,7 +79,6 @@
|
|||
#define SOCK_BUF(x) (char *)(x)
|
||||
#define SOCK_CBUF(x) (const char *)(x)
|
||||
#define SOCK_IOCTL ioctlsocket
|
||||
#define SOCK_POLL WSAPoll
|
||||
#define SOCK_CLOSE closesocket
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#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;
|
||||
pfd.fd = _sock;
|
||||
pfd.events = POLLIN;
|
||||
|
@ -351,7 +397,7 @@ Error NetSocketPosix::poll(PollType p_type, int timeout) const {
|
|||
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);
|
||||
|
||||
|
@ -359,6 +405,7 @@ Error NetSocketPosix::poll(PollType p_type, int timeout) const {
|
|||
return ERR_BUSY;
|
||||
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
Error NetSocketPosix::recv(uint8_t *p_buffer, int p_len, int &r_read) {
|
||||
|
|
Loading…
Reference in New Issue