我在boost :: asio上有一个TCP服务器,它监听连接,并在获取后开始使用boost :: asio :: write在循环中发送数据块。
bool TcpServer::StartTcpServer(std::shared_ptr<boost::asio::io_service> io_service)
{
m_ioservice = io_service;
m_acceptor.reset(new boost::asio::ip::tcp::acceptor(*m_ioservice, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), m_port)));
m_socket = std::unique_ptr<boost::asio::ip::tcp::socket>(new boost::asio::ip::tcp::socket(*m_ioservice));
m_socket->close();
m_acceptor->async_accept(*m_socket, m_peer_endpoint, boost::bind(&TcpServer::AcceptHandler, this, boost::asio::placeholders::error));
m_io_thread.reset(new std::thread([this]{
try
{
this->m_ioservice->run();
}
catch(const boost::system::system_error & err){print logs}
catch(...){print another logs}
}));
}
void TcpServer::AcceptHandler(const boost::system::error_code &ec)
{
while(true)
{
try
{
boost::asio::write( *m_socket, boost::asio::buffer(data->c_str(), data->size()), boost::asio::transfer_all());
}
catch(const boost::system::system_error & err){print logs}
catch(...){print another logs}
}
}
如果我手动停止接收器,则会抛出并正确处理损坏管道的异常。但有时会发生破裂的管道(我认为连接不良的原因)并且异常会在所有捕获中奇迹般地落空并且应用程序终止:
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
检查核心我发现它发生在boost :: asio :: write中,起源于io_service :: run()。我做错了什么?
此外,我尝试使用async_write重写TCP服务器,但它仍然会发生,但不会经常发生。
EDIT1:如果我手动停止接收器导致管道损坏,我会得到完全相同的异常和完全相同的callstack,但这个我可以处理。
EDIT2:根据我的理解,现在不可捕获的异常可能是因为过多的数据通过套接字发送得太快。但不确定。
答案 0 :(得分:1)
terminate
中的错误消息确实解释了发生了什么。 boost::exception_detail::clone_impl
失败了。在不深入研究代码的情况下,我假设它用于实现异常类的复制构造函数。如果此复制构造函数在异常处理期间抛出异常,它将绕过异常块,异常将向上传播。 (即使您通过引用捕获,仍可由编译器进行复制。)
现在我不知道为什么复制构造函数失败了;知道问题还不够。但是与异步I / O相关的this question有一个非常相似的问题,而且问题的关键似乎是在异常处理之前销毁了shared_ptr
。看起来很相似。