Skip to content
This repository was archived by the owner on Feb 20, 2021. It is now read-only.
This repository was archived by the owner on Feb 20, 2021. It is now read-only.

Synchronous client connection (with no timeout set) to non listening socket blocks indefinitely [SOLVED] #214

Open
@fammollo

Description

@fammollo

Hello,

I am testing on Windows 7 the C++ library redis3m, based upon hiredis and boost, and I am using the hiredis client/Win32_Interop libraries (git tag 2.8.17.3) provided by you.

I have compiled from scratch all the needed components, both hiredis and redis3m along with all its dependencies, with Visual Studio Express 2013 for Windows Desktop, the only change I have made to your project files is to use the DLL version of the C/C++ runtime libraries.
The resulting executable uses only static libraries, I have no additional dependencies upon DLLs exept for those provided by Windows itself; Dependency Walker shows for the debug version: KERNEL32.DLL, WS2_32.DLL, MSVCP120D.DLL, MSVCR120D.DLL, USER32.DLL, ADVAPI32.DLL.

I am writing you here because I have experienced this issue: it seems that a blocking connection to redis with no timeout set, initiated by calling redisConnect (host, port) blocks indefinitely if the remote port is not open, I would have expected instead returning from the function and c->err set to an appropriate error.

Stepping inside the library code, I saw that inside the function _redisContextConnectTcp:

  • connect (redis_connect_impl, actually) is called and it returns EINPROGRESS because WSAGetLastError returns 10035 (WSAEWOULDBLOCK)

  • After that redisContextWaitReady is called, and the execution blocks indefinitely inside it, specifically when calling poll on the socket:

    if (errno == EINPROGRESS) {
    int res;

    if ((res = poll(wfd, 1, msec)) == -1) {
    

After reading here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms741669%28v=vs.85%29.aspx

and here: http://curl.haxx.se/mail/lib-2012-10/0038.html

At first I tried changing the polled events from just POLLOUT to POLLOUT | POLLERR, but then a legitimate connection did not work anymore (I didn't investigate this), so in the end I chose to try to use select instead of poll (keeping POLLERR, so that internally the socket is added to the excepSet).

I opted to enable using poll only if the OS is at least Windows 8 by changing this check:

if (IsWindowsVersionAtLeast(HIBYTE(_WIN32_WINNT_WIN6), LOBYTE(_WIN32_WINNT_WIN6), 0)) {

to this one:

IsWindowsVersionAtLeast(HIBYTE(0x0602), LOBYTE(0x0602), 0)) {

(the SDK provided by VS 2003 Express does not now anything about the _WIN8/_WINBLUE defines)

but there were again some problems (caused, I think, by the code not being really maintained/tested) so in the end I debugged and modified the code and I finally got it working.

I don't know if using select already works in the 2.8 branch (or in some other version); if it isn't, I would like to contribute my modification to you (if it's appreciated).

Thank you in advance and best regards
Fabrizio

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions