title: Boost asio: io service is blocked during destruction step more some handler trouble
body: <p>To manage tcp communication i'm using boost asio version 1.48 with x64 project setting on visual studio 10 with sdk 7.1 and windows 7.</p>
  
  <p>I designed a class with inner members:</p>
  
  <ul>
  <li>asio IO Service.</li>
  <li>asio tcp ipv4 Socket.</li>
  <li>asio Strand.</li>
  <li>a list of received Messages.</li>
  <li>a pointer to a boost thread.</li>
  </ul>
  
  <p>During debug runtime, process follow the next steps :</p>
  
  <ol>
  <li>construct the object and inner attributs io service, socket, strand
  and a pointer to a thread.</li>
  <li>create an async connection with the created socket</li>
  <li>listen to message header with an async read.</li>
  <li>create a thread which call io service run.</li>
  <li>A header message is read, listen to message body called in a strand
  with async read.</li>
  <li>stack the message and call treatement in IOservice via post function
  and a handler.</li>
  <li>listen to message header with an async read.</li>
  <li>repeat n time step 5 to 7.</li>
  <li>cancel then close the socket.</li>
  <li>stop and reset the io service.</li>
  <li>destroy the object.</li>
  </ol>
  
  <p>I have two major troubles:</p>
  
  <p>=> The connection handler is never called but connection is done !
  Handler function:= </p>
  
  <pre><code>void CManager::HandleConnect(const boost::system::error_code&amp; error, boost::asio::ip::tcp::resolver::iterator it)
  </code></pre>
  
  <p>=> during destroying process program block in file boost\asio\detail\impl\win_iocp_io_service.ipp l358:</p>
  
  <pre><code>BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &amp;bytes_transferred,
          &amp;completion_key, &amp;overlapped, block ? gqcs_timeout : 0);
  </code></pre>
  
  <p>I don't understand why?</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>My code:</p>
  
  <p>Note that my worst trouble is program block during destruction of msgManager instance !</p>
  
  <p>best Regards.</p>
  
  <pre><code>CManager::CManager(const char* _ipAdress, const char* _port):    
      m_MsgFactory(),
      m_IOService(),
      m_Socket(m_IOService),
      m_Strand(m_IOService),
      m_ReceivedMsgs(),
      m_pThread(nullptr)
  {
      Start( _ipAdress, _port);
  }
  
  CManager::~CManager(void)
  {
  }
  
  CManager::TThread* CManager::GetThread(void)
  {
      return m_pThread;
  }
  
  void CManager::Start(const char* _ipAdress, const char* _port)
  {
      CreateConnection( _ipAdress, _port);
  
      if(nullptr == m_pThread)
      {
          m_pThread = new TThread( boost::bind(&amp;boost::asio::io_service::run,&amp;m_IOService) );
      }
  }
  
  void CManager::Stop()
  {
      CloseConnection();
  
      m_IOService.stop();
      m_IOService.reset();
  }
  
  void CManager::CreateConnection(const char* _ipAdress, const char* _port)
  {
      boost::asio::ip::tcp::resolver resolver(m_IOService);
  
      boost::asio::ip::tcp::resolver::query query( boost::asio::ip::tcp::v4(), std::string(_ipAdress), std::string(_port) );
      boost::asio::ip::tcp::resolver::iterator endPointIt = resolver.resolve(query);
  
      // Start an asynchronous connect operation.
      boost::asio::async_connect(m_Socket, endPointIt, boost::bind(&amp;CManager::HandleConnect, this, boost::asio::placeholders::error, endPointIt));
  
      //Previous handler is never called. Without next code, asio log in consol show a cancel message !
      Listen();
  }
  
  void CManager::HandleConnect(const boost::asio::placeholders::error&amp; error, TResolver::iterator it)
  {
      if (!error)
      {
          Listen();
      }
  }
  
  void CManager::CloseConnection()
  {
      m_Socket.cancel();
      m_Socket.close();
  }
  
  void CManager::Listen(void)
  {
          TMsgPtr pMsg(new TMsg());
  
          CMsgBase::TMsgBuffer headerBuffer;
          if(!pMsg-&gt;GetHeaderBuffer(headerBuffer))
          {            
              return;
          }
  
          boost::asio::async_read(m_Socket,
                                  headerBuffer,
                                  m_Strand.wrap( boost::bind(&amp;CManager::HandleReadMsg, this, boost::asio::placeholders::error, pMsg) ) );        
  }
  
  void CManager::HandleReadMsg(const boost::asio::placeholders::error&amp; error, TMsgPtr _pMsgBase )
  {
      if (!error &amp;&amp; nullptr != _pMsgBase &amp;&amp;  true == _pMsgBase-&gt;HasBody() )
      {
          CMsgBase::TMsgBuffer       bodyBuffer;
          _pMsgBase-&gt;GetBodyBuffer( bodyBuffer );
  
          //Next treatment.
          boost::asio::async_read(m_Socket,
                                  bodyBuffer,
                                  m_Strand.wrap( boost::bind(&amp;CManager::HandleMsg, this, boost::asio::placeholders::error, _pMsgBase) ) );
      }
      else
      {
          Listen();
      }
  }
  
  void CManager::HandleMsg(const boost::asio::placeholders::error&amp; error, TMsgPtr _pMsgBase )
  {
      if (!error &amp;&amp; nullptr != _pMsgBase)
      {
          m_ReceivedMsgs.push_back( _pMsgBase );
  
          //post will not call the function directly but postpone the call in io service.
          m_IOService.post( boost::bind(&amp;CManager::TranslateMsg, this) );
      }
  
      //Still listen for next messages.
      Listen();
  }
  
  int _tmain(int argc, char* argv[])
  {
      try
      {
          /*Some code*/
  
          boost::thread_group threadGroup;
  
          CManager msgManager( ipAddress, ipPort );
          threadGroup.add_thread( msgManager.GetThread() );
  
          /*Some code*/
  
          msgManager.Stop();
          threadGroup.join_all();
  
          /*Some code*/
      }
      catch (std::exception&amp; e)
      {
          /*Some code*/
      }
  
      return 0;
  }
  </code></pre>