title: How to properly shutdown asio tcp server?
body: <p>What is the proper way to shutdown an asynchronous boost asio tcp server? My currently solution usually deadlocks in the destructor. Why?</p>
  
  <pre><code>class connection;
  
  typedef std::set&lt;shared_ptr&lt;connection&gt;&gt; connection_set;
  
  class connection : public enable_shared_from_this&lt;connection&gt;
  {    
      shared_ptr&lt;tcp::socket&gt;         socket_; 
  
      std::array&lt;char, 8192&gt;          data_;
  
      shared_ptr&lt;connection_set&gt;      connection_set_;
  public:
      static shared_ptr&lt;connection&gt; create(shared_ptr&lt;tcp::socket&gt; socket, shared_ptr&lt;connection_set&gt; connection_set)
      {
          auto con = shared_ptr&lt;connection&gt;(new connection(std::move(socket), std::move(connection_set)));
          con-&gt;read_some();
          return con;
      }
  
      void on_next(const event&amp; e)
      {   
          // async_write_some ...
      }
  
  private:
      connection(shared_ptr&lt;tcp::socket&gt; socket, shared_ptr&lt;connection_set&gt; connection_set) 
          : socket_(std::move(socket))
          , connection_set_(std::move(connection_set))
      {
      }
  
      void handle_read(const boost::system::error_code&amp; error, size_t bytes_transferred) 
      {       
          if(!error)
          {
              on_read(std::string(data_.begin(), data_.begin() + bytes_transferred));     
              read_some();
          }  
          else if (error != boost::asio::error::operation_aborted)
              connection_set_-&gt;erase(shared_from_this());
          else
              read_some();
      }
  
      void handle_write(const shared_ptr&lt;std::vector&lt;char&gt;&gt;&amp; data, const boost::system::error_code&amp; error, size_t bytes_transferred)
      {
          if(!error)          
          {
          }
          else if (error != boost::asio::error::operation_aborted)
              connection_set_-&gt;erase(shared_from_this());
      }
  
      void read_some()
      {
          socket_-&gt;async_read_some(boost::asio::buffer(data_.data(), data_.size()), std::bind(&amp;connection::handle_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
      }
  
      void on_read(std::string str)
      {
          // parse the string...
      }
  };
  
  class tcp_observer
  {
      boost::asio::io_service             service_;
      tcp::acceptor                       acceptor_;
      std::shared_ptr&lt;connection_set&gt;     connection_set_;
      boost::thread                       thread_;
  
  public:
      tcp_observer(unsigned short port)
          : acceptor_(service_, tcp::endpoint(tcp::v4(), port))
          , thread_(std::bind(&amp;boost::asio::io_service::run, &amp;service_))
      {
          start_accept(); 
      }
  
      ~tcp_observer()
      {
          // Deadlocks...
          service_.post([=]
          {
              acceptor_.close();
              connection_set_-&gt;clear();
          });
          thread_.join();
      }
  
      void on_next(const event&amp; e)
      {
          service_.post([=]
          {
              BOOST_FOREACH(auto&amp; connection, *connection_set_)
                  connection-&gt;on_next(e);
          });
      }   
  private:        
      void start_accept() 
      {
          auto socket = std::make_shared&lt;tcp::socket&gt;(service_);
          acceptor_.async_accept(*socket, std::bind(&amp;tcp_observer::handle_accept, this, socket, std::placeholders::_1));
      }
  
      void handle_accept(const shared_ptr&lt;tcp::socket&gt;&amp; socket, const boost::system::error_code&amp; error) 
      {
          if (!acceptor_.is_open())
              return;
  
          if (!error)     
              connection_set_-&gt;insert(connection::create(socket, connection_set_));
  
          start_accept();
      }
  };
  </code></pre>