Why does async_connect() call listen()?

Hi there,
By coincidence, I ended up looking at a stack trace where my application
calls async_connect() on a asio::ip::tcp::socket. Two things took me by
surprise:
1. Asio calls listen() under the hood. Why does it do that when I'm just
trying to make an outbound TCP connection?
2. If the listen() call above is indeed required, why does it happen on
the same thread where I call async_connect()? I thought the point of the
method was to defer the work to the reactor? (For what it's worth, I've had
a case on a customer's machine where the call to listen() would hang for 30
seconds before returning -- probably because of a bad firewall -- causing
my entire app to hang since the code assumes async_connect() is indeed
async.)
I've included the full stack trace below.
Thanks,
Soren
0:000> k
ChildEBP RetAddr
0117db50 0f681c65 WS2_32!listen
0117db70 0f691013 EvoClr!boost::asio::detail::socket_ops::listen+0x35
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\socket_ops.ipp
@ 658]
0117dbd8 0f690e9f
EvoClr!boost::asio::detail::socket_select_interrupter::open_descriptors+0x163
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\socket_select_interrupter.ipp
@ 78]
0117dbe4 0f690cc0
EvoClr!boost::asio::detail::socket_select_interrupter::socket_select_interrupter+0xf
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\socket_select_interrupter.ipp
@ 42]
0117dc1c 0f690c1e
EvoClr!boost::asio::detail::select_reactor::select_reactor+0x70
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\select_reactor.ipp
@ 48]
0117dc44 0f17837e
EvoClr!boost::asio::detail::service_registry::createboost::asio::detail::select_reactor+0x4e
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\service_registry.hpp
@ 81]
0117dc80 0f6909e9
EvoClr!boost::asio::detail::service_registry::do_use_service+0x9e
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\service_registry.ipp
@ 123]
0117dca0 0f6908ee
EvoClr!boost::asio::detail::service_registry::use_serviceboost::asio::detail::select_reactor+0x39
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\service_registry.hpp
@ 49]
0117dca8 0f68fab0
EvoClr!boost::asio::use_serviceboost::asio::detail::select_reactor+0xe
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\impl\io_service.hpp
@ 34]
0117dcbc 0f68f731
EvoClr!boost::asio::detail::win_iocp_socket_service_base::get_reactor+0x30
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\win_iocp_socket_service_base.ipp
@ 620]
0117dce4 0f68f6f1
EvoClr!boost::asio::detail::win_iocp_socket_service_base::start_connect_op+0x11
[c:\private\src\vendor\boost_1_55_0_sdk\include\boost\asio\detail\impl\win_iocp_socket_service_base.ipp
@ 550]
0117dd28 0f68ed22
EvoClr!boost::asio::detail::win_iocp_socket_serviceboost::asio::ip::tcp::async_connect

"Soren Dreijer"
The call is made by the class socket_select_interrupter. The socket it is calling listen() on is an internal one bound to 127.0.0.1. If a firewall interferes with that then the firewall is horribly bugged. I believe the socket is set up so that a thread that is blocking on a call to ::select() (for example in io_service::run()), can be interrupted from another thread. This interruption is probably used when io_service::stop() is called for example.
It only has to defer work that would block or that the documentation explicitly promises it will defer. Regards Niklas Angare

"Nathaniel Fries"
Soren said only that he calls async_connect(). Imagine he then calls io_service::run(). That thread is now blocked in a call to ::select() waiting for the connect to finish. If another thread then did anything with that io_service, such as another async call or indeed stop(), the original thread would have to be interrupted somehow. Regards, Niklas Angare
participants (4)
-
Nathaniel Fries
-
Niklas Angare
-
Soren Dreijer
-
Soren Dreijer