Skip to content

Commit

Permalink
Windows: pass writefds also as exceptfds to select()
Browse files Browse the repository at this point in the history
winsock notifies connect() failures on exceptfds instead of writefds.
Fixes aria2GH-969
Fixes aria2GH-975
  • Loading branch information
nmaier authored and Vijayanand Nandam committed Mar 3, 2018
1 parent 8957d2b commit a26e815
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 15 deletions.
21 changes: 12 additions & 9 deletions src/SelectEventPoll.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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_) {
Expand All @@ -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__
Expand All @@ -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

Expand All @@ -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();
Expand Down
11 changes: 5 additions & 6 deletions src/SelectEventPoll.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ class SelectEventPoll : public EventPoll {
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<sock_t, SocketEntry> SocketEntrySet;
SocketEntrySet socketEntries_;
Expand All @@ -161,12 +166,6 @@ class SelectEventPoll : public EventPoll {
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:
Expand Down

0 comments on commit a26e815

Please sign in to comment.