Boost logo

Boost Users :

Subject: [Boost-users] [asio] SSL async_shutdown() never finishes if called when async_read_some() is in progress
From: Alexander D. (alexdems_at_[hidden])
Date: 2018-04-06 07:56:16


Hello,

I'm writing a middleware which basically adds an SSL layer to the connection between a client and a server. The connection is bidirectional, so I need to read from each side and write to the other. The client can also close the connection at any time, in which case async_shutdown() must be called on the server's stream.

The problem is, often the shutdown happens when the program is waiting on the server through async_read_some(), and the shutdown will never finish.

The following code illustrates this issue:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>

int main(int argc, char* argv[])
{
  try
  {
    boost::asio::io_context io_context;
    boost::asio::streambuf buffer;

    boost::asio::ssl::context ctx(boost::asio::ssl::context::tlsv12);
    ctx.set_verify_mode(boost::asio::ssl::verify_none);

    boost::asio::ssl::stream<boost::asio::ip::tcp::socket>
    sock(io_context, ctx);

    sock.next_layer().connect(boost::asio::ip::tcp::endpoint(
        boost::asio::ip::make_address("127.0.0.1"), 4433));
    sock.handshake(boost::asio::ssl::stream_base::client);

    /* "async_shutdown" won't appear unless async_read_some()
     * is commented out */
    sock.async_read_some(buffer.prepare(1024),
        [](boost::system::error_code, size_t)
        {std::cout << "async_read_some" << std::endl;});

    sock.async_shutdown([](boost::system::error_code)
        {std::cout << "async_shutdown" << std::endl;});

    io_context.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}

To reproduce, start up an SSL server:
  openssl genrsa -out key.pem 2048
  openssl req -new -sha256 -key key.pem -out csr.csr
  openssl req -x509 -sha256 -days 365 -key key.pem -in csr.csr -out server.pem
  openssl s_server -key key.pem -cert server.pem
and run the program. Notice that "async_shutdown" does not finish even if the server is killed.

In practice, this leaks the memory of the shutdown handler and whatever is bound to it. The only solution I can think of would be to cancel the read operation, but there's no portable way in asio to do this.

Can someone point out how to solve this?

Cheers,

Alexander


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net