Opened 9 years ago
Last modified 5 years ago
#8795 reopened Bugs
async_connect incorrectly reports success on failure
Reported by: | Owned by: | chris_kohlhoff | |
---|---|---|---|
Milestone: | To Be Determined | Component: | asio |
Version: | Boost 1.63.0 | Severity: | Regression |
Keywords: | Cc: |
Description
I've found a regression between 1.53 to 1.54; if you compile boost/libs/asio/example/cpp11/chat/chat_client.cpp and point it at a host and port that doesn't exist or refuses the connection, instead of coming back with an error, such as host not found or connection refused, it reports success (on the conversion to bool). (you might want to embellish the example with a std::cout << error_code.message() << std::endl;)
This appears to be the case across Linux, Darwin, iOS and Android.
synchronous connect seems to work correctly (i.e., echo/blocking_tcp_echo_client.cpp)
Change History (22)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
I encountered this while working with websocketpp library which uses boost asio. connect returns success despite the failure to connect. websocketpp returns the same success to the application.
comment:3 by , 9 years ago
I also have same problem with boost 1.54.0. The error code from async_connect()'s callback is always success in spite of connection failed.
comment:4 by , 9 years ago
I have the same problem. I created a workaround in my code by calling connect and then posting the response to the async_connect handle. This, of course, blocks the calling thread :(.
comment:5 by , 9 years ago
Confirmed also in boost trunk as of 20130801 (1.55) linux ubuntu saucy 64 bits. A regression that is causing services that are supposed to reconnect on failure to proceed.
Quite easy to reproduce using the async_client in the examples without any listening http server. Add a debug trace (should get connection refused):
root@pookie:/tmp# g++ -c -o client.o client.cpp root@pookie:/tmp# g++ -o client client.o -lboost_system -lboost_thread -lpthread root@pookie:/tmp# ./client localhost /index.html handle_connect Error: system:0 Error: Broken pipe
Thanks R.
comment:6 by , 9 years ago
You cannot even use boost::asio::ip::tcp::iostream because the connect method makes use of async_connect. I would consider this a huge bug and I am surprised there are only a few responses to this ticket. I spend a considerable amount of time debugging my projects today to find this bug (I use Arch Linux and they updated recently).
comment:7 by , 9 years ago
For my own use, I found that simply inserting:
if (ec) return true;
at line 524 of boost/asio/detail/impl/socket_ops.ipp (i.e. in non_blocking_connect() after the check for error::already_started and before calling getsockopt()) has proven to be a reasonable workaround. Again, as I do not understand the intent of the changes from 1.53.0, I am not sure that this is the correct bugfix, so YMMV.
comment:8 by , 9 years ago
I confirm the bug in BOOST 1.54. The connect handler reports success although the connect attempt failed.
comment:11 by , 9 years ago
On CentOS 6.4 (64bit), upgrade from 1.49.0 to 1.54.0 introduced this issue for me. The error code in connect handler reports success and the socket appears to be is_open().
comment:12 by , 9 years ago
Summary: | async_connect oncorrectly reports success on failure → async_connect incorrectly reports success on failure |
---|
comment:14 by , 9 years ago
For me this fix worked
if (ec == asio::error::connection_refused) return true;
at line 524 of boost/asio/detail/impl/socket_ops.ipp
It seems that when connect
returns ECONNREFUSED
then getsockopt
returns no error.
comment:15 by , 9 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:16 by , 8 years ago
With Boost 1.55 running on Windows 8.1 I was seeing a single false connection. On Boost 1.56 I see repeated false connections, over and over again.
By "false connections" I mean that the connect handler for async_connect gets called right away (when the other end of the socket is not there), with error_code zero and where conn->socket.is_open() return true. Stepping into the boost code I see in win_iocp_io_service.ipp line 405 result_ec is 10057 (WSAENOTCONN). The next line of code (ec = boost::system::error_code();) sets ec to zero.
Does anyone else see this?
follow-up: 18 comment:17 by , 7 years ago
I am experiencing this bug using MSVC 14 and Boost 1.60.
No asynchronous solution in sight. Finnicky.
comment:18 by , 7 years ago
Replying to anonymous:
I am experiencing this bug using MSVC 14 and Boost 1.60.
No asynchronous solution in sight. Finnicky.
UPDATE: Replacing asio::ip::tcp::acceptor.cancel() with asio::ip::tcp::acceptor.close() in another thread, fixes some oddity within a shared asio::io_service...
comment:19 by , 6 years ago
Boost 1.63.0, Windows 10 64-bit.
Also shows no error despite the connection failed.
comment:20 by , 6 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Version: | Boost 1.54.0 → Boost 1.63.0 |
comment:20 by , 6 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Upgrading my own code to use 1.54.0 instead of 1.53.0, I also encountered this same problem. It appears to be due to the refactoring of the socket_ops::non_blocking_connect() function, which now calls socket_ops::connect() and then (unless getting back boost::asio::error::already_started), calls socket_ops::getsockopt with SO_ERROR. The problem is that the call to ::connect() within socket_ops::connect() has already effectively cleared the error (and set errno appropriately), and ec already contains the desired error code, so the call to getsockopt ends up clearing the error information from ec, making it appear to have succeeded.
Unfortunately I am not familiar enough with the intent of the changes to propose the correct solution, although I suspect it would be to only call socket_ops::getsockopt() if the call to socket_ops::connect() did not itself return an error.