@@ -3246,8 +3246,11 @@ inline int poll_wrapper(struct pollfd *fds, nfds_t nfds, int timeout) {
32463246
32473247template <bool Read>
32483248inline ssize_t select_impl (socket_t sock, time_t sec, time_t usec) {
3249+ #if defined(__APPLE__) || defined(_WIN32)
3250+ // Use select() on macOS and Windows for better performance
32493251#ifdef __APPLE__
32503252 if (sock >= FD_SETSIZE) { return -1 ; }
3253+ #endif
32513254
32523255 fd_set fds, *rfds, *wfds;
32533256 FD_ZERO (&fds);
@@ -3260,9 +3263,15 @@ inline ssize_t select_impl(socket_t sock, time_t sec, time_t usec) {
32603263 tv.tv_usec = static_cast <decltype (tv.tv_usec )>(usec);
32613264
32623265 return handle_EINTR ([&]() {
3266+ #ifdef _WIN32
3267+ // On Windows, the first parameter of select() is ignored
3268+ return select (0 , rfds, wfds, nullptr , &tv);
3269+ #else
32633270 return select (static_cast <int >(sock + 1 ), rfds, wfds, nullptr , &tv);
3271+ #endif
32643272 });
32653273#else
3274+ // Use poll() on Linux and other POSIX systems
32663275 struct pollfd pfd;
32673276 pfd.fd = sock;
32683277 pfd.events = (Read ? POLLIN : POLLOUT);
@@ -3283,25 +3292,43 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
32833292
32843293inline Error wait_until_socket_is_ready (socket_t sock, time_t sec,
32853294 time_t usec) {
3295+ #if defined(__APPLE__) || defined(_WIN32)
3296+ // Use select() on macOS and Windows.
3297+ // WSAPoll() on Windows has known performance issues with localhost
3298+ // connections. See: https://daniel.haxx.se/blog/2012/10/10/wsapoll-is-broken/
32863299#ifdef __APPLE__
3300+ // On macOS, check if socket descriptor exceeds FD_SETSIZE
32873301 if (sock >= FD_SETSIZE) { return Error::Connection; }
3302+ #endif
32883303
3289- fd_set fdsr, fdsw;
3304+ fd_set fdsr, fdsw, fdse ;
32903305 FD_ZERO (&fdsr);
32913306 FD_ZERO (&fdsw);
3307+ FD_ZERO (&fdse);
32923308 FD_SET (sock, &fdsr);
32933309 FD_SET (sock, &fdsw);
3310+ FD_SET (sock, &fdse);
32943311
32953312 timeval tv;
32963313 tv.tv_sec = static_cast <long >(sec);
32973314 tv.tv_usec = static_cast <decltype (tv.tv_usec )>(usec);
32983315
32993316 auto ret = handle_EINTR ([&]() {
3300- return select (static_cast <int >(sock + 1 ), &fdsr, &fdsw, nullptr , &tv);
3317+ #ifdef _WIN32
3318+ // On Windows, the first parameter of select() is ignored
3319+ return select (0 , &fdsr, &fdsw, &fdse, &tv);
3320+ #else
3321+ return select (static_cast <int >(sock + 1 ), &fdsr, &fdsw, &fdse, &tv);
3322+ #endif
33013323 });
33023324
33033325 if (ret == 0 ) { return Error::ConnectionTimeout; }
33043326
3327+ if (ret > 0 && (FD_ISSET (sock, &fdse))) {
3328+ // Socket has an exception (connection failed)
3329+ return Error::Connection;
3330+ }
3331+
33053332 if (ret > 0 && (FD_ISSET (sock, &fdsr) || FD_ISSET (sock, &fdsw))) {
33063333 auto error = 0 ;
33073334 socklen_t len = sizeof (error);
@@ -3313,6 +3340,7 @@ inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
33133340
33143341 return Error::Connection;
33153342#else
3343+ // Use poll() on Linux and other POSIX systems
33163344 struct pollfd pfd_read;
33173345 pfd_read.fd = sock;
33183346 pfd_read.events = POLLIN | POLLOUT;
0 commit comments