9
votes

I have a TCP server on boost::asio, it listens for a connection and after getting it starts sending data blocks using boost::asio::write in a loop.

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}
    }
}

If I manually stop a receiver an exception about broken pipe is thrown and handled properly. But sometimes broken pipe happens (cause of bad connection I suppose) and the exception miraculously falls through all the catches and the application is terminated:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'

Examining the core I see that it happened in boost::asio::write originated in io_service::run(). What am I doing wrong?

Also I tried to rewrite the TCP server using async_write but it still happens, no so often though.

EDIT1: if I stop the receiver manually causing broken pipe I get the exactly same exception and the exactly same callstack but this one I can handle.

EDIT2: from what I understand right now non-catchable exception may be the result of too much data sent too fast through the socket. Not sure though.

1
Are you sure it is an exception? What do you get if you catch(...)?wally
I have a printout saying "terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >' what(): write: Broken pipe". catch(...) does not catch anything.Nikolay Kovalenko
Is it throwing from some function that has an exception specification? Have a look at this answer.wally
You can't catch exceptions thrown inside another thread; that is probably your problem here.jplatte
If possible, could a minimal reproducible example be provided?Tanner Sansbury

1 Answers

1
votes

The error message in terminate actually does explain what's happening. boost::exception_detail::clone_impl is failing. Without digging through the code, I'd assume it's used to implement the copy constructor of the exception class. If this copy constructor throws an exception during exception handling, it will bypass the exception block and the exception will propagate upwards. (Even when you catch by reference, copies may still be made by the compiler.)

Now I don't know why the copy constructor is failing; there's not enough in the question to know. But this question relating to asynchronous I/O had a very similar problem, and there the crux seems to have been that a shared_ptr was being destroyed before exception processing. Looks similar.