断开连接后正确杀死asio stable_timer

时间:2019-04-21 17:06:31

标签: c++ ssl asio

我使用独立的asio编写了一个异步SSL套接字实现,并在服务器重置/关闭连接后努力使其重新连接。我对asio库很陌生,所以请多多包涵。

由于io_context::run,即使在断开连接后,调用steady_timer的线程仍保持阻塞。我的close()逻辑负责重置套接字资源,还负责尝试终止计时器。这是我的代码现在的样子:

创建我的异步作业:

timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

在我的close()方法中:

timer.expires_at(std::chrono::steady_clock::now());
timer.cancel();

根据boost docscancel()应该:

  

取消所有正在等待计时器的异步操作。

也许我误解了这一点,但我可以想象这也会取消绑定到io_context的异步作业,但事实并非如此。 io_context::run永远不会释放,并且会造成死锁。

这是我的计时器处理程序的样子:

void ssl_socket::heartbeat() {
    spdlog::get("console")->trace("heartbeat called");

    if (connected_) {
        write(heartbeat_token);
        spdlog::get("console")->trace("heartbeat sent");
    }

    timer.expires_at(std::chrono::steady_clock::now() + std::chrono::seconds(heartbeat_interval));
    timer.async_wait(std::bind(&ssl_socket::heartbeat, this));

}

我想让处理程序不必验证它是否应该更新计时器,并让close()处理该计时器(如果可能)。

1 个答案:

答案 0 :(得分:1)

您忽略了错误代码。

  

根据增强文档,cancel()应该:

     
    

取消所有正在等待计时器的异步操作。

  

这有点误导。阅读cancel函数的完整说明时,您会看到:

  

此函数强制完成任何未决的异步等待   针对计时器的操作。每个取消操作的处理程序   将会以boost::asio::error::operation_aborted错误被调用   代码。

这意味着,您的处理程序将由cancel函数调用,并且由于您的处理程序只是重新设置了到期时间并再次等待,因此循环永远不会结束。您需要检查错误代码,如果已设置,请退出循环。

if(error) return;
相关问题