简体   繁体   English

Boost.Asio async_handshake无法取消

[英]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). 当使用Boost Asio SSL流启动async_handshake ,然后在握手完成之前实现截止期限计时器以取消/关闭流时,该程序将崩溃并出现缓冲区溢出异常(在Windows上,我还没有尝试过Linux)。 The crash is somewhere after the socket is close d, and external handlers finish executing, but before the run() command completes. 崩溃发生在套接字close d之后,外部处理程序完成执行,但在run()命令完成之前。

Is there a reason why the socket cannot be closed when an SSL handshake is in progress? 进行SSL握手时,为什么无法关闭套接字? Or is this a bug in Boost Asio? 还是这是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. 为了澄清,称handle_timeout()之前handle_handshake()是由IO服务,即会在崩溃io_service::run()方法。

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()如下所示:

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. 所以不,这不是Boost.Asio本身的错误。

We've ran into that one as well. 我们也碰到了那个。 My colleague (AW) found that culprit. 我的同事(AW)发现了罪魁祸首。 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. 握手在后台使用读写操作,这些操作需要取消,并且握手操作需要正确完成(带有operation_aborted错误),然后才能安全地关闭袜子。 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;
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM