owacoder owacoder - 1 month ago 13
C++ Question

Boost.Asio async_handshake cannot be canceled

When initiating an

async_handshake
with a Boost Asio SSL stream, and then implementing a deadline timer to cancel/close the stream before the handshake completes, the program will crash with a buffer overflow exception (on Windows, I haven't tried Linux yet). The crash is somewhere after the socket is
close
d, and external handlers finish executing, but before the
run()
command completes.

Is there a reason why the socket cannot be closed when an SSL handshake is in progress? Or is this a bug in Boost Asio?

class Connection
{
void connect_handler(const boost::system::error_code &err)
{
...
ssock->async_handshake(boost::asio::ssl::stream_base::client,
boost::bind(&Connection::handle_handshake, this, _1));
...
}

void handle_handshake(const boost::system::error_code &err)
{
// CONNECTED SECURELY
}

void handle_timeout()
{
// HANDLE SSL SHUTDOWN IF ALREADY CONNECTED...
...
ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
ssock->close();
delete ssock;
}

...

boost::asio::ssl::stream<boost::asio::ip::tcp::socket> *ssock;
};


To clarify, calling
handle_timeout()
before
handle_handshake()
is called by the IO service will crash in the
io_service::run()
method.

Answer

The problem is the socket object is being destroyed before the asynchronous handlers complete. To cancel the pending/queued handlers, use io_service::stop() like this:

io_service.stop(); // Stop the IO service to prevent handlers from executing
ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
ssock->close();
delete ssock;

So no, it is not a bug in Boost.Asio itself.

Comments