无法从boost::asio::io_service::run捕获异常

Unable to catch exception from boost::asio::io_service::run

本文关键字:service run 捕获异常 io asio boost      更新时间:2023-10-16

我在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> >'

通过检查内核,我发现它发生在源自io_service::run()的boost::asio::write中。我做错了什么?

此外,我还尝试使用async_write重写TCP服务器,但这种情况仍然存在,但并不经常发生。

编辑1:如果我手动停止接收器导致管道破裂,我会得到完全相同的异常和完全相同的调用堆栈,但这次我可以处理。

编辑2:据我目前所知,不可捕获的异常可能是由于通过套接字发送的数据过多而过快造成的。但不确定。

terminate中的错误消息实际上解释了发生了什么。boost::exception_detail::clone_impl出现故障。在不深入研究代码的情况下,我假设它用于实现异常类的复制构造函数。如果此复制构造函数在异常处理过程中抛出异常,它将绕过异常块,并且异常将向上传播。(即使通过引用捕获,编译器仍可能进行复制。)

现在我不知道复制构造函数为什么失败;这个问题没有足够的答案。但这个与异步I/O有关的问题也有一个非常类似的问题,关键似乎是shared_ptr在异常处理之前被销毁了。看起来很相似。