Ticket #8795 (closed Bugs: fixed)

Opened 4 years ago

Last modified 9 months ago

async_connect incorrectly reports success on failure

Reported by: benpope81@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.54.0 Severity: Regression
Keywords: Cc:


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

comment:1 Changed 4 years ago by stephen.pope@…

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.

comment:2 Changed 4 years ago by naidu.trk@…

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 Changed 4 years ago by anonymous

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 Changed 3 years ago by junk@…

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 Changed 3 years ago by Ramon Casellas <ramon.casellas@…>

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 Changed 3 years ago by jft@…

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 Changed 3 years ago by anonymous

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 Changed 3 years ago by mvd

I confirm the bug in BOOST 1.54. The connect handler reports success although the connect attempt failed.

comment:9 Changed 3 years ago by david.keegan@…

Yes, I've hit this problem too on Linux.

comment:10 Changed 3 years ago by anonymous

I confirm the problem in 1.54.0 boost.

comment:11 Changed 3 years ago by anonymous

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 Changed 3 years ago by anonymous

  • Summary changed from async_connect oncorrectly reports success on failure to async_connect incorrectly reports success on failure

comment:13 Changed 3 years ago by Antonio Di Monaco <tony@…>

Confirmed on Slackware64, using boost 1.54.0

comment:14 Changed 3 years ago by agazso@…

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 Changed 3 years ago by chris_kohlhoff

  • Status changed from new to closed
  • Resolution set to fixed

Minimal fix on trunk in [85738]. Subsequent cleanup in [85739]. Merged to release in [85838].

comment:16 Changed 2 years ago by anonymous

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?

comment:17 follow-up: ↓ 18 Changed 9 months ago by anonymous

I am experiencing this bug using MSVC 14 and Boost 1.60.

No asynchronous solution in sight. Finnicky.

comment:18 in reply to: ↑ 17 Changed 9 months ago by anonymous

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...


Add a comment

Modify Ticket

Change Properties
<Author field>
as closed
The resolution will be deleted. Next status will be 'reopened'

E-mail address and user name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.