2017-07-04 2 views
0

Je ne comprends pas comment je dois fermer un socket ssl boost::asio. Je l'ai essayé de plusieurs façons, mais il soulève toujours un Segmentation fault dans un moment.Erreur de segmentation (SIGSEGV) utilisant boost asio 1.64 lors de la tentative de fermeture d'un socket SSL

Je lis le post suivant pour résoudre cette situation: boost asio ssl async_shutdown always finishes with an error?

Plus précisément, je suis en train de mettre en œuvre le

Partya initie un arrêt() et attend PartyB de répondre avec un shutdown()

Notez que le client et le serveur s'exécutent dans localhost.

est Ci-dessous le code client:

typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLSocket; 

MyClass::MyClass(const std::string &url, 
    const std::string &port) throw() : 
    m_socket(NULL), m_url(url), m_port(port), m_isConnected(false) 
{ 
} 

void MyClass::disconnect() 
{ 
    // See the section "the disconnect method" 
} 

bool MyClass::tryConnect() throw() 
{ 
    boost::asio::io_service ioService; 
    boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); 
    m_socket = new SSLSocket(ioService, ctx); 

    tcp::resolver resolver(ioService); 
    tcp::resolver::query query(m_url, m_port); 

    tcp::resolver::iterator end; 
    tcp::resolver::iterator endpoint_iterator = resolver.resolve(query); 

    boost::system::error_code error = boost::asio::error::host_not_found; 
    boost::asio::connect(m_socket->lowest_layer(), endpoint_iterator, error); 

    if(endpoint_iterator == end || error) 
    { 
    m_isConnected = false; 
    } 
    else 
    { 
    m_socket->set_verify_mode(boost::asio::ssl::verify_none); 
    m_socket->handshake(SSLSocket::client); 

    m_isConnected = true; 
    } 

    return m_isConnected; 
} 

void MyClass::write(const std::string &message) 
{ 
    boost::asio::write(*m_socket, boost::asio::buffer(message)); 
} 

std::string MyClass::readUntil(const std::string &until) 
{ 
    boost::asio::read_until(*m_socket, response, until); 
    ... 
    return response; 
} 

int main() 
{ 
    MyClass mc(...); 

    while(true) 
    { 
    bool connected = mc.isConnected(); 

    if(!connected) 
    { 
     connected = mc.tryConnect(); 
    } 

    if(connected) 
    { 
     mc.send(...); 
     std::string resp = mc.readUntil(...); 
     mc.disconnect(); 
    } 
    } 
} 

La méthode déconnexion

J'ai lu le post lié dans les commentaires et je l'ai mis à jour le serveur ssl et le client. Maintenant, les deux effectuent l'opération shutdown() pour fermer la connexion ssl correctement, mais j'ai toujours une erreur lors de la fermeture du socket.

J'ai mis à jour la méthode disconnect() (qui est toujours là où le programme se bloque) comme suit:

... 
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> *m_socket; 
... 
void MyClass::disconnect() 
{ 
    // Shutdown the connection 
    // TODO is this the correct way to close a boost asio socket? 
    if(m_socket != NULL) 
    { 
    std::cout << "shutting down the socket, thread = " << 
     pthread_self() << std::endl; 

    // I have checked that the thread is always the same, so the problem 
    // is not related with race conditions or similar. 

    boost::system::error_code ec; 
    m_socket->lowest_layer().shutdown(
     boost::asio::ip::tcp::socket::shutdown_both, ec); 

    std::cout << 
     "Shut down, err = " << ec << ", " << 
     "Category: " << ec.category().name() << std::endl; 

    if(!ec) 
    { 
     std::cout << "closing the socket, thread = " << 
     pthread_self() << std::endl; 

     if(m_socket->lowest_layer().is_open()) 
     { 
     m_socket->lowest_layer().close(ec); 
     } 

     std::cout << 
     "Socket closed, err = " << ec << ", " << "Category: " << 
     ec.category().name() << std::endl; 

     if(!ec) 
     { 
     std::cout << "Deleting socket... " << std::endl; 
     delete m_socket; 
     m_socket = NULL; 
     std::cout << "Socket deleted" << std::endl; 
     } 
    } 
    } 

    m_isConnected = false; 
} 

Le backtrace d'erreur

Le bkactrace (à partir de la méthode de déconnexion) est ici:

#0 0x4158114f in boost::system::error_code::operator=<boost::asio::error::basic_errors> (this=0x1d, val=boost::asio::error::operation_aborted) 
    at .../include/boost/system/error_code.hpp:344 
#1 0x41587308 in boost::asio::detail::epoll_reactor::deregister_descriptor (this=0x46463045, descriptor=27, [email protected]: 0x8151ea8, 
    closing=true) at .../include/boost/asio/detail/impl/epoll_reactor.ipp:351 
#2 0x41588550 in boost::asio::detail::reactive_socket_service_base::close (this=0x812efbc, impl=..., ec=...) 
    at .../include/boost/asio/detail/impl/reactive_socket_service_base.ipp:104 
#3 0x415885da in boost::asio::stream_socket_service<boost::asio::ip::tcp>::close (this=0x812efa8, impl=..., ec=...) 
    at .../include/boost/asio/stream_socket_service.hpp:174 
#4 0x41588630 in boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >::close (this=0x812ef08, ec=...) 
    at .../include/boost/asio/basic_socket.hpp:385 
#5 0x41576383 in MyClass::disconnect (this=0x80a6f58) at ... 

En examinant le frame 1, on peut voir que l'erreur que le boost crée est boost::asio::error::operation_aborted;

En outre, l'exécution du processus avec gdb, simetimes je vois l'échec d'assertion suivante:

pthread_mutex_lock.c:312: __pthread_mutex_lock_full: Assertion `(-(e)) != 3 || !robust' failed. 
+0

SIGABRT indique souvent un échec d'assertion. Avez-vous inspecté la trace de la pile de l'accident? Comment exactement tuez-vous ce processus? Dans votre extrait de code, il n'y a pas de threads et pas de gestion de signal. Aussi, vous appelez 'resolver.resolve (query)' deux fois sans raison. – VTT

+0

La réponse à cette question peut vous aider: [Quelle est la bonne façon de déconnecter en toute sécurité une socket SSL asio?] (Https://stackoverflow.com/questions/32046034/what-is-the-proper-way-to- solidement-déconnecter-un-asio-ssl-socket) – kenba

Répondre

0

J'ai trouvé le problème.

I a été Openning la douille dans un procédé similaire:

void connect() 
{ 
    ... 
    boost::asio::io_service m_ioService 
    ... 
    m_sock = new SSLSocket(m_ioService, ...) 
} 

Lorsque la méthode retourne connect, m_ioService est hors de portée, de sorte que les accidents de la douille depuis la ioService a été supprimé. Notez que le m_ioService est passé par référence, en outre, il est non-copiable.