From 1fe6cc73563c3804a0c70947aa76fd50650f1abb Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Mon, 31 Jul 2017 15:41:40 +0200 Subject: [PATCH] Windows: pass writefds also as exceptfds to select() winsock notifies connect() failures on exceptfds instead of writefds. Fixes GH-969 Fixes GH-975 --- src/SelectEventPoll.cc | 21 ++++++++++++--------- src/SelectEventPoll.h | 11 +++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/SelectEventPoll.cc b/src/SelectEventPoll.cc index c709dccc..824c5088 100644 --- a/src/SelectEventPoll.cc +++ b/src/SelectEventPoll.cc @@ -174,11 +174,6 @@ void SelectEventPoll::poll(const struct timeval& tv) memcpy(&rfds, &rfdset_, sizeof(fd_set)); memcpy(&wfds, &wfdset_, sizeof(fd_set)); -#ifdef __MINGW32__ - fd_set efds; - FD_ZERO(&efds); - FD_SET(dummySocket_, &efds); -#endif // __MINGW32__ #ifdef ENABLE_ASYNC_DNS for (auto& i : nameResolverEntries_) { @@ -195,7 +190,11 @@ void SelectEventPoll::poll(const struct timeval& tv) do { struct timeval ttv = tv; #ifdef __MINGW32__ - retval = select(fdmax_ + 1, &rfds, &wfds, &efds, &ttv); + // winsock will report non-blocking connect() errors in exceptfds, unlike + // posix, which will mark such sockets as writable. + // So just pass in our write socket set to exceptfds, too, to get connect() + // error notifications on Windows. + retval = select(fdmax_ + 1, &rfds, &wfds, &wfds, &ttv); #else // !__MINGW32__ retval = select(fdmax_ + 1, &rfds, &wfds, nullptr, &ttv); #endif // !__MINGW32__ @@ -215,7 +214,8 @@ void SelectEventPoll::poll(const struct timeval& tv) } else if (retval == -1) { int errNum = errno; - A2_LOG_INFO(fmt("select error: %s", util::safeStrerror(errNum).c_str())); + A2_LOG_INFO(fmt("select error: %s, fdmax: %d", + util::safeStrerror(errNum).c_str(), fdmax_)); } #ifdef ENABLE_ASYNC_DNS @@ -240,13 +240,16 @@ void checkFdCountMingw(const fd_set& fdset) void SelectEventPoll::updateFdSet() { + FD_ZERO(&rfdset_); + FD_ZERO(&wfdset_); #ifdef __MINGW32__ + FD_SET(dummySocket_, &rfdset_); + FD_SET(dummySocket_, &wfdset_); fdmax_ = dummySocket_; #else // !__MINGW32__ fdmax_ = 0; #endif // !__MINGW32__ - FD_ZERO(&rfdset_); - FD_ZERO(&wfdset_); + for (auto& i : socketEntries_) { auto& e = i.second; sock_t fd = e.getSocket(); diff --git a/src/SelectEventPoll.h b/src/SelectEventPoll.h index 311d4134..d5753095 100644 --- a/src/SelectEventPoll.h +++ b/src/SelectEventPoll.h @@ -151,6 +151,11 @@ private: fd_set rfdset_; fd_set wfdset_; sock_t fdmax_; +#ifdef __MINGW32__ + // Winsock select() doesn't work if no socket is in FD_SET. We add + // this dummy socket to work around this problem + sock_t dummySocket_; +#endif // __MINGW32__ typedef std::map SocketEntrySet; SocketEntrySet socketEntries_; @@ -161,12 +166,6 @@ private: AsyncNameResolverEntrySet nameResolverEntries_; #endif // ENABLE_ASYNC_DNS -#ifdef __MINGW32__ - // Winsock select() doesn't work if no socket is in FD_SET. We add - // this dummy socket to work around this problem - sock_t dummySocket_; -#endif // __MINGW32__ - void updateFdSet(); public: