Skip to content

Commit 690c8e2

Browse files
rsomla1silvakid
authored andcommitted
Bug#29865097: HANG IN CONNECT WHEN TIMEOUT IS SET TO 10
1 parent 86a52e4 commit 690c8e2

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

cdk/foundation/socket_detail.cc

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ const error_category& resolve_error_category()
292292
static void throw_socket_error()
293293
{
294294
#ifdef _WIN32
295-
throw_error(WSAGetLastError(), winsock_error_category());
295+
int error = WSAGetLastError();
296+
if (error)
297+
throw_error(error, winsock_error_category());
296298
#else
297299
throw_system_error();
298300
#endif
@@ -658,25 +660,41 @@ Socket connect(const char *host_name, unsigned short port,
658660
if (connect_result == SOCKET_ERROR && errno == EINPROGRESS)
659661
#endif
660662
{
661-
auto timeout = duration_cast<microseconds>(
662-
deadline - system_clock::now()
663-
).count();
664663

665-
int select_result = poll_one(
666-
socket, POLL_MODE_CONNECT, true,
667-
0 == timeout_usec ? 0 : timeout > 0 ? timeout : 1
668-
);
664+
int select_result = 0;
665+
666+
do{
667+
668+
auto timeout = duration_cast<microseconds>(
669+
deadline - system_clock::now()
670+
).count();
671+
672+
select_result = poll_one(
673+
socket, POLL_MODE_CONNECT, true,
674+
0 == timeout_usec ? 0 : timeout > 0 ? timeout : 1
675+
);
676+
// Note: if poll_one() returns 0 then, according to POSIX specs:
677+
// A value of 0 indicates that the call timed out and no file descriptors have been selected
678+
// Due to a bug on WSApool, it may return 0 even if no timeout occur..
679+
// So we will check if timeout occurs and try again if not
669680

670-
if (select_result == 0 && (timeout_usec > 0) &&
671-
(std::chrono::system_clock::now() >= deadline))
681+
} while ((select_result == 0) &&
682+
((timeout_usec == 0) ||
683+
(std::chrono::system_clock::now() < deadline)
684+
)
685+
);
686+
687+
if ((timeout_usec > 0) &&
688+
(std::chrono::system_clock::now() >= deadline))
672689
{
673690
// Throw the error in milliseconds, which we did not adjust.
674691
// Otherwise the user will be confused why the timeout
675692
// in the error message is smaller than defined
676693
// (original timeout minus DNS resolution time)
677694
throw Connect_timeout_error(timeout_usec / 1000);
678695
}
679-
else if (select_result < 0)
696+
697+
if (select_result < 0)
680698
throw_socket_error();
681699
else
682700
check_socket_error(socket);
@@ -858,8 +876,9 @@ DIAGNOSTIC_POP_CDK
858876
#endif
859877

860878
if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
861-
check_socket_error(socket);
862-
879+
{
880+
check_socket_error(socket);
881+
}
863882

864883
return result;
865884
}

0 commit comments

Comments
 (0)