2016-05-26 23 views
9

Ho un server TCP su boost :: asio, ascolta una connessione e dopo averlo inizia a inviare blocchi di dati usando boost :: asio :: write in un ciclo.Impossibile rilevare l'eccezione da boost :: asio :: io_service :: eseguire

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

Se si arresta manualmente un ricevitore, un'eccezione relativa al tubo rotto viene generata e gestita correttamente. Ma tubo talvolta accade rotture (causa di cattiva connessione suppongo) e l'eccezione miracolosamente cade attraverso tutte le catture e l'applicazione viene terminata:

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

Esaminando il nucleo vedo che è accaduto a boost :: asio :: scrivere originato in io_service :: run(). Che cosa sto facendo di sbagliato?

Inoltre, ho provato a riscrivere il server TCP utilizzando async_write, ma succede ancora, non così spesso però.

EDIT1: se il ricevitore viene interrotto manualmente causando un guasto del tubo, ottengo la stessa identica eccezione e lo stesso callstack ma questo posso gestirlo.

EDIT2: da quello che ho capito ora l'eccezione non intercettabile può essere il risultato di troppi dati inviati troppo velocemente attraverso il socket. Non sono sicuro però.

+0

Sei sicuro che sia un'eccezione? Cosa ottieni se prendi (...) '? – wally

+0

Ho una stampa che dice "termina chiamata dopo aver lanciato un'istanza di 'boost :: exception_detail :: clone_impl >' what(): write: Broken pipe ". prendere (...) non cattura nulla. –

+0

Si sta lanciando da qualche funzione che ha una specifica di eccezione? Dai un'occhiata a [questa risposta] (http://stackoverflow.com/a/26332289/1460794). – wally

risposta

1

Il messaggio di errore in terminate effettivamente spiega cosa sta succedendo. boost::exception_detail::clone_impl non funziona. Senza scavare nel codice, presumo che sia usato per implementare il costruttore di copie della classe di eccezioni. Se questo costruttore di copie genera un'eccezione durante la gestione delle eccezioni, ignorerà il blocco delle eccezioni e l'eccezione si propagherà verso l'alto. (Anche se si cattura per riferimento, le copie possono ancora essere eseguite dal compilatore.)

Ora non so perché il costruttore della copia ha esito negativo; non c'è abbastanza nella domanda da sapere. Ma l'this question relativo all'I/O asincrono aveva un problema molto simile, e il problema sembra essere che uno shared_ptr sia stato distrutto prima dell'elaborazione delle eccezioni. Sembra simile