Boost C++ Libraries: Ticket #13587: ssl::stream::async_shutdown() never completes when async_read is active https://svn.boost.org/trac10/ticket/13587 <p> I have a connected ssl::stream. If I do an asio::async_read followed by an async_shutdown on the stream, the read operation will complete with stream_truncated error (as expected) but the async_shutdown operation never completes (i.e. handler never gets called). See a minimal reproduce below. </p> <p> Environment: Debian stretch, gcc 6.3.0, Boost 1.67, BoringSSL. </p> <p> My questions: </p> <ol><li>Is it allowed to call async_shutdown on an ssl::stream when there is an async_read pending? </li><li>If yes, is the above behavior expected? </li><li>If not, how do I gracefully shutdown an SSL stream when an async_read is pending? And is this restriction documented anywhere? </li></ol><p> Code: </p> <pre class="wiki">#include &lt;boost/asio.hpp&gt; #include &lt;boost/asio/connect.hpp&gt; #include &lt;boost/asio/ip/tcp.hpp&gt; #include &lt;boost/asio/ssl/error.hpp&gt; #include &lt;boost/asio/ssl/stream.hpp&gt; #include &lt;cstdlib&gt; #include &lt;functional&gt; #include &lt;iostream&gt; #include &lt;memory&gt; #include &lt;string&gt; using tcp = boost::asio::ip::tcp; // from &lt;boost/asio/ip/tcp.hpp&gt; namespace ssl = boost::asio::ssl; // from &lt;boost/asio/ssl.hpp&gt; void fail(boost::system::error_code ec, char const* what) { std::cerr &lt;&lt; what &lt;&lt; ": " &lt;&lt; ec.message() &lt;&lt; "\n"; } class session : public std::enable_shared_from_this&lt;session&gt; { tcp::resolver resolver_; ssl::stream&lt;tcp::socket&gt; stream_; std::string buffer_; public: explicit session(boost::asio::io_context&amp; ioc, ssl::context&amp; ctx) : resolver_(ioc) , stream_(ioc, ctx) { } void run( char const* host, char const* port) { // Set SNI Hostname (many hosts need this to handshake successfully) if(! SSL_set_tlsext_host_name(stream_.native_handle(), host)) { boost::system::error_code ec{static_cast&lt;int&gt;(::ERR_get_error()), boost::asio::error::get_ssl_category()}; std::cerr &lt;&lt; ec.message() &lt;&lt; "\n"; return; } resolver_.async_resolve( host, port, std::bind( &amp;session::on_resolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } void on_resolve( boost::system::error_code ec, tcp::resolver::results_type results) { if(ec) return fail(ec, "resolve"); boost::asio::async_connect( stream_.next_layer(), results.begin(), results.end(), std::bind( &amp;session::on_connect, shared_from_this(), std::placeholders::_1)); } void on_connect(boost::system::error_code ec) { if(ec) return fail(ec, "connect"); stream_.async_handshake( ssl::stream_base::client, std::bind( &amp;session::on_handshake, shared_from_this(), std::placeholders::_1)); } void on_handshake(boost::system::error_code ec) { if(ec) return fail(ec, "handshake"); std::cout &lt;&lt; "Connected" &lt;&lt; std::endl; boost::asio::async_read(stream_, boost::asio::dynamic_buffer(buffer_), std::bind( &amp;session::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2)); stream_.async_shutdown( std::bind( &amp;session::on_shutdown, shared_from_this(), std::placeholders::_1)); } void on_read( boost::system::error_code ec, std::size_t) { if(ec) return fail(ec, "read"); std::cout &lt;&lt; "Message received" &lt;&lt; std::endl; } void on_shutdown(boost::system::error_code ec) { std::cout &lt;&lt; "Closed" &lt;&lt; std::endl; } }; int main(int argc, char** argv) { boost::asio::io_context ioc; ssl::context ctx{ssl::context::sslv23_client}; std::make_shared&lt;session&gt;(ioc, ctx)-&gt;run("www.google.com", "443"); ioc.run(); return EXIT_SUCCESS; } </pre><p> The program will output </p> <pre class="wiki">Connected read: stream truncated </pre><p> and hangs. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/13587 Trac 1.4.3