Broken pipe after writing to socket

為{幸葍}努か 提交于 2019-12-11 04:18:09

问题


In my network library I can do asynchronous writes to the network if I run() and restart() the io_context manually.

I'm now trying to make things scale by adding a thread pool:

.hpp

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;

  asio::io_context m_io_context;

  asio::thread_pool m_workers;

  asio::executor_work_guard<asio::io_context::executor_type> m_work_guard;

  /// \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(); });
}

Which manages connections:

.hpp

struct abstract_connection : connection {
  explicit abstract_connection(const std::shared_ptr<pool> &pool) noexcept;

  ~abstract_connection() override;
      packet m_buffer;

      asio::local::stream_protocol::endpoint m_endpoint;

      asio::generic::stream_protocol::socket m_socket;

      asio::io_context::strand m_strand;
    };

.cpp

abstract_connection::abstract_connection(const std::shared_ptr<pool> &pool) noexcept
        : m_params{pool->m_params},
          m_config{pool->m_config},
          m_endpoint{pool->m_config.socket},
          m_socket{pool->m_io_context},
          m_strand{pool->m_io_context} {
      m_socket.connect(m_endpoint);
      m_socket.non_blocking(true);
    }

abstract_connection::~abstract_connection() {
      std::error_code ec;
      m_socket.shutdown(asio::generic::stream_protocol::socket::shutdown_both, ec);
      m_socket.close();
    }

Now comes the confusing park. On the ctor of a concrete connection object I need to do a handshake, along with a handshake on the destructor of the same class. Which does not happen because the socket object seems to be behaving in odd ways:

If I send data asyncrhonously, nothing gets written to the socket and sometimes I get a broken pipe error:

asio::dispatch(m_strand, [&]() {
          m_buffer = write::startup(m_params);
          asio::async_write(m_socket, asio::buffer(m_buffer), [](std::error_code ec, std::size_t len) {});
        });

If I do a synchronous write I get a broken pipe error before I can read from the socket:

std::error_code ec;
        auto startup = write::startup(m_params);
        asio::write(m_socket, asio::buffer(startup), ec);
        if (set_error(ec)) {
          std::cerr << " XXX " << ec.message() << std::endl;
          return;
        }

        m_buffer.reserve(327);
        asio::read(m_socket, asio::buffer(m_buffer), ec);
        std::cerr << ec.message() << std::endl;
        std::cerr << m_buffer.size() << std::endl;

The connection is being done over a unix socket and I have socat sitting between both, so I can see data coming and going, along with the broken pipe messages. Trying to connect to the remote using a third party tool works, with all relevant data appearing in socat, so I believe the problem is in my code.

How can I debug what is going on with the socket?


回答1:


Based on the code you posted, it seems your boost::asio::thread_pool just goes out of scope to early. Your abstract_connection class just takes a const std::shared_ptr<pool> &pool, which means your abstract connection instances are not holding a reference count on your thread pool. References to std::shared_ptr are not making sense in general because of this, let your abstract_connection just take a std::shared_ptr<const pool> pool in its constructor, which you should copy or move in a member with the same type.




回答2:


I solved the problem by making the socket blocking (non_blocking(false)) which I would not have thought of without Superlokkus' answer.



来源:https://stackoverflow.com/questions/54887817/broken-pipe-after-writing-to-socket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!