Home > Blockchain >  Boost async_read reads zero bytes from pipe
Boost async_read reads zero bytes from pipe

Time:10-11

I'm trying to asynchrosouly read from a pipe using boost::asio::async_read, but it reads zero bytes everytime. However, I can succussfuly read from the pipe using the read function(unistd.h);

here's my code:

    auto io = make_shared<boost::asio::io_service>();
    auto work = make_shared<boost::asio::io_service::work>(*io);
    int read_end = atoi(argv[0]);
    auto pipe_read = make_shared<boost::asio::readable_pipe>(*io, read_end);
    string message;

    boost::thread_group worker_threads;
    for(int i = 0; i < 1; i  )
    {
        // I'm calling io->run() inside the worker thread.
        worker_threads.create_thread(boost::bind(&workerThread, io));
    }

    // The handler function gets the number of bytes read, which is always zero.
    boost::asio::async_read(*pipe_read, boost::asio::buffer(message, 5), boost::bind(&handler, _1, _2));
    cout << message << endl;

    work.reset();
    worker_threads.join_all();
    return 0;

Any help would be much appreciated.

CodePudding user response:

Given a

std::string message;

then asio::buffer(message) has size 0 (because the string is empty).

The overload taking a size asio::buffer(message, 5) can only limit the size, but doesn't provide it. So it is still size 0.

This explains your symptoms. Instead,

std::string message(5, '\0');
auto b = asio::buffer(message);

Or, alternatively,

std::string message;
message.resize(1024); // cue Bill Gates miss-quote
auto b = asio::buffer(message, 5);

Or even use dynamic buffers:

std::string message;
auto b = asio::dynamic_buffer(message/*, 5*/);

Live Demo

Showing a modernized version also fixing the various bugs I remarked:

Live On Coliru

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <iostream>
namespace asio = boost::asio;

void handler(boost::system::error_code ec, size_t xfr) {
    std::cout << "Received " << xfr << " bytes (" << ec.message() << ")\n";
}

int main(int argc, char** argv) {
    asio::thread_pool ioc(1); // or more threads
    assert(argc > 1);
    int  read_end  = atoi(argv[1]);
    auto pipe_read = make_shared<boost::asio::readable_pipe>(ioc, read_end);

    std::string message(5, '\0');
    boost::asio::async_read(*pipe_read, asio::buffer(message), &handler);

    ioc.join();
    std::cout << message << std::endl;
}

Prints

./a.out 0 <<< "HELLO WORLD"
Received 5 bytes (Success)
HELLO
  • Related