0
votes

I have a simple TCP server with one thread with the asio loop, and a thread pool to do the computation. I'm able to listen to connections write something to it in the main thread. But I can't wait the answer of the worker thread because the connection is immediately closed after getting accepted.

I tried using a deadline timer but for some reason it gets called immediately with "Aborted operation" error.

The whole process I want to achieve is:

  • Accept connection
  • write something
  • send a task to the worker pool
  • wait for the answer from the worker (I'm using a thread safe queue to read message from the worker pool)
  • write the answer to the socket
  • close connection

Here is my code

class tcp_connection
: public boost::enable_shared_from_this<tcp_connection>
{
  public:
    typedef boost::shared_ptr<tcp_connection> pointer;

    static pointer create(boost::asio::io_service& io_service)
    {
      return pointer(new tcp_connection(io_service));
    }

    tcp::socket& socket()
    {
      return socket_;
    }

    void start()
    {
      message_ = "Write me in 5 sec";
      boost::asio::deadline_timer t(service_, boost::posix_time::seconds(5));
      t.async_wait(boost::bind(&tcp_connection::writeAfter, shared_from_this(), boost::asio::placeholders::error));
    }

  private:
    tcp_connection(boost::asio::io_service& io_service)
      : service_(io_service), socket_(io_service)
    {
    }

    void writeAfter(const boost::system::error_code&) {
      std::cout << "writing to socket" << std::endl;
      boost::asio::async_write(socket_, boost::asio::buffer(message_),
          boost::bind(&tcp_connection::handle_write, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }


    void handle_write(const boost::system::error_code& /*error*/,
        size_t /*bytes_transferred*/)
    {
    }

    boost::asio::io_service &service_;
    tcp::socket socket_;
    std::string message_;
};

EDIT: Debug log

@asio|1462018696.996630|0*1|[email protected]_wait
@asio|1462018696.996675|0|[email protected]
@asio|1462018696.996694|0*2|[email protected]_accept
@asio|1462018696.996714|0*3|[email protected]_wait
@asio|1462018696.996736|>1|ec=system:125

As we can see the cancel is called on the timer but I don't have a single cancel in my code so I don't know why it is called.

Thank you very much for your help

2

2 Answers

1
votes

Are you still listening for other connections after you create a tcp_connection?

Since you haven't called async_read or async_read_some for your new connection, io_service.run() for that thread may simply have completed...

If you start the deadline timer in the tcp_connection constructor, it should keep io_service.run() going and send the message.

0
votes

I found why.

There was a mess with shared pointers and my connection object was destroyed. So was the TCP object. The connection was close.

Thanks @kenba for your help !