2
votes

I have a native posix socket which i am trying to asynchronously read from using boost::asio::async_read. However when I do this:

// io_stream and fd are passed by reference to this function
asio::posix::stream_descriptor stream(io_stream);
stream.assign(fd);

boost::system::error_code ec;

asio::async_read(stream, buffer,
                 asio::transfer_at_least(1),
                 boost::bind(doRead,
                             asio::placeholders::error,
                             asio::placeholders::bytes_transferred));
size_t count = io_service.run_one(ec);

The count variable is set with 0 and the doRead handler is never called and ec contains no errors. However if I replace the async read with a synchronous read:

size_t count = asio::read(stream, buffer,
                          asio::transfer_at_least(1));

This works and I get the expected amount of data back in the count variable.

My test cases using a fd created by "int pipe(int pipefd[2]);" and passing data through that work fine with asio::async_read so I am thinking it could be a couple of options:

  • Some how the native descriptor I am passing isn't compatible with async_read in some way so it is failing silently. I have tried creating it with blocking on and off with no avail.
  • The io_service and the posix::stream_descriptor is some how not connected so the io_service never tries to run the read. Could this be due to me passing the io_service around by reference? (And within a couple of threads as well for that matter?)
1
A stream_descriptor works just fine with a descriptor from the read end of a pipe, see this answer. I suspect your second bullet is the cause of the behavior you see. Please edit your question and include a short, self contained, correct example for us to analyze.Sam Miller
I will get one together on Monday at work as I don't have the code here at home, thanks!Rory Hart

1 Answers

1
votes

I found the issue.

I was calling io_service.stop() in the initialization function of the owning object as it can be re-initialised. I wasn't calling io_service.reset() after the call to stop however and io_service won't run after a stop until reset has been called.

A lesson in RTFM as both stop and reset document this.

However the boost::system::error_code variable didn't reflect this state which is a bit frustrating as it would have saved me messing around.