lundi 25 février 2019

Connection pool destructor prevents network communication in destructor of connection objects

I have a connection pool that uses the new thread_pool with 2 threads. I also have 2 connections on my pool. The connection pool is implemented thus:

.hpp

/// \brief Connection pool.
    struct pool : public std::enable_shared_from_this<pool> {
      pool(const pool &) = delete;
      auto operator=(const pool &) -> pool & = delete;
      explicit pool(pool_parameters config, db_parameters params) noexcept;
      ~pool();

      /// \brief Run loop.
      asio::io_context m_io_context;

      /// \brief Used to keep the io_context from running out of work.
      asio::executor_work_guard<asio::io_context::executor_type> m_work_guard;

      /// \brief Thread pool where tasks are asynchronously executed.
      asio::thread_pool m_workers;

      /// \brief Container to hold connections.
      std::vector<std::unique_ptr<dbc::connection>> m_connections;
    };

.cpp

pool::pool(pool_parameters config, db_parameters params) noexcept
    : m_config{std::move(config)},
      m_params{std::move(params)},
      m_work_guard{asio::make_work_guard(m_io_context)},
      m_workers{m_config.thread_pool_size} {
  m_connections.reserve(m_config.connection_pool_size);
  asio::post(m_workers, [&]() { m_io_context.run(); });
}

pool::~pool() {
  std::cerr << "~pool" << std::endl;
  m_work_guard.reset();
  m_workers.join();
  m_io_context.stop();
}

I also have a connection object that does a connection handshake on the constructor and a disconnect handshake on the destructor.

The problem is that by the time the connection is destroyed the pool has already stopped the work guard and so no packets are sent to the remote system.

How can I force the disconnect handshake to be done before the work guard is destroyed? I can add a manual disconnect method to each connection object but I'd like to stick to RAII.

Aucun commentaire:

Enregistrer un commentaire