Reputation: 4873
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.
Upvotes: 1
Views: 2597
Reputation: 63
We've ran into that one as well. My colleague (AW) found that culprit. Handshake uses read and write operations behind the scene, those need to be cancelled, and the handshake operation needs to properly finish (with operation_aborted error) before the ssock can be safely closed. Tested solution for this is below:
void handle_timeout() {
...
// cancel pending read/write operations
ssock->lowest_layer().cancel();
// finish shutdown on next tick of event loop
boost::asio::post([=] {
ssock->shutdown(boost::asio::ip::tcp::socket::shutdown_both);
ssock->close();
delete ssock;
});
}
Upvotes: 2
Reputation: 4873
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.
Upvotes: -1