2010-10-13 6 views
13

Un autre dans la saga de moi-même continue contre Boost.Asio ...Boost.Asio: Opération ANNULEE async_read

J'ai un simple client asynchrone et le serveur qui utilisent pour communiquer async_write et async_read. Le client peut écrire avec succès des octets sur le socket, mais le serveur ne les voit jamais; mon gestionnaire de lecture sur le serveur échoue avec "Opération annulée". Je suis porté à croire que cela peut être un problème de synchronisation avec le client écrit les données après le serveur a essayé de le lire et a échoué, mais j'aurais pensé que les données seraient en attente sur le socket de toute façon (sauf si la prise a été fermée entre temps).

Pour tester cela, je simplement re-couru l'opération de lecture dans le gestionnaire d'erreur, à savoir

read_handler() 
{ 
    if (!error) { 
     /* bytes read */ 
    } else { 
     async_read(socket, buffer, read_handler) 
    } 
} 

Mais tout cela m'a fait était une erreur de segmentation dans pthread_mutex_lock via un appel à async_receive.

Quelqu'un pourrait-il me diriger dans le sens de toute information pertinente (ou, mieux encore, dites-moi exactement ce que je fais mal;))?

MISE À JOUR: Le serveur et le client sont basés sur l'exemple du serveur de chat dans les Asio docs, avec le client et le serveur à la fois en cours d'exécution dans le même processus (cela pourrait être un problème pensant un peu plus ils utilisent à la fois la? même io_service ...); asynchrone et utilisant Boost 1.44.0. Je travaille sur OS X mais cela est également reproductible sur Linux.

MISE À JOUR II: Mon intuition était correcte et si le serveur et le client reçoivent des objets io_service distincts, async_read voit les octets sur le socket. Cela donne toujours une erreur de segmentation dans boost::asio::detail::kqueue_reactor::post_immediate_completion qui semble provenir du io_service.run(). Avant d'aller plus loin, utilise-t-on des objets séparés io_service la bonne approche?

+0

Quelle plateforme vous exécutez sur? –

+0

La plate-forme est OSX et Linux; les deux présentent le même problème. – kfb

+0

Je pense que nous devons voir un peu plus de votre code pour avoir une chance de deviner ce que vous avez mal fait! Il serait également utile de savoir quelque chose au sujet de votre installation - le client et le serveur fonctionnent-ils sur des machines identiques ou différentes, par exemple? Les deux sont écrits en utilisant boost :: asio? Quelle version de Boost utilisez-vous (asio a changé récemment)? – dajames

Répondre

25

Opération annulée (le code d'erreur "opération_aborted") est envoyé lorsque le socket est closed ou annulé.

Votre connexion est probablement hors de portée. Peut-être qu'il m'est arrivé d'oublier d'attacher les async_handlers à un pointeur shared_from_this(). I.e. Vous devez attacherai vos gestionnaires comme ceci:

async_read(m_socket, 
      boost::asio::buffer((void*)m_buffer, m_header_size), 
      boost::bind(&TcpConnection::handleRead, 
      shared_from_this(), 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 

Et PAS comme ceci:

async_read(m_socket, 
      boost::asio::buffer((void*)m_buffer, m_header_size), 
      boost::bind(&TcpConnection::handleRead, 
      this, //<- This will go out of scope and the socket will be closed 
      boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
+2

Merci, j'ai eu un crash dans une région totalement différente, mais aussi avec un message d'erreur 'Operation cancellation'. Et c'est qu'un "ceci" est sorti de la portée! Heureusement, j'ai trouvé votre réponse après le débogage pendant des heures ... – Chris

+0

qui est la meilleure réponse de tous. erreur complètement étrange. diagnostic absolument sur place. – Alex

+0

et pourquoi exactement la connexion est hors de portée, quand cela est passé? – bryanph