Boost.Asio - named pipe poll

I am trying to listen for input on a named pipe. I am using Boost.Asio stream_descriptor and async_read on Linux. The problem is that the io_service :: run () call is blocked, as I want, until the first read. After that, it simply calls the handler immediately with the "End of file" error, although I am trying to connect more async_reads to it. The code I have is equivalent to the following:

boost::asio::io_service io_service;
int fifo_d = open("/tmp/fifo", O_RDONLY);
boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
while (true)
{
    // buffer and handler probably aren't important for the purposes of this question
    boost::asio::async_read(fifo, buffer, handler);
    io_service.run();
}

Only the first async_read works as I expect. Subsequent async_reads are returned immediately. The only way I worked as I want is to close and reopen the named pipe, but it looks like a hack:

boost::asio::io_service io_service;
while (true)
{
    int fifo_d = open("/tmp/fifo", O_RDONLY);
    boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
    boost::asio::async_read(fifo, buffer, handler);
    io_service.run();
    close(fifo_d);
}

Can someone tell me what I am doing wrong?

UPDATE: "" , , :

int fifo_d = open("/tmp/fifo", O_RDONLY);
boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
while (true) {
    try {
        boost::asio::read(fifo, boost::asio::buffer(buffer));
    }
    catch (boost::system::system_error& err) {
        // It loops here with "read: End of file" error
        std::cout << err.what() << std::endl;
    }
}
+4
2

. run() . , reset() ( ).

, // , async_*?

Demos

  • iostream fd:

    Live On Coliru

    #include <iostream>
    #include <fstream>
    
    int main() {
        std::ifstream fifo("/tmp/fifo");
    
        std::string word;
        size_t lineno = 0;
        while (fifo >> word) {
            std::cout << "word: " << ++lineno << "\t" << word << "\n";
        }
    }
    
  • , fd, - , file_descriptor Boost IOstreams:

    Live On Coliru

    #include <boost/iostreams/device/file_descriptor.hpp>
    #include <boost/iostreams/stream.hpp>
    #include <iostream>
    #include <fcntl.h>
    
    int main() {
        namespace io = boost::iostreams;
        using src = io::file_descriptor_source;
        io::stream<src> fifo(src(open("./fifo", O_RDONLY), io::file_descriptor_flags::close_handle));
    
        std::string word;
        size_t number = 0;
        while (fifo >> word) {
            std::cout << "word: " << ++number << "\t" << word << "\n";
        }
    }
    

:

word: 1 hello
word: 2 world
+1

, boost:: asio. ioservice::run() , . ioservice , reset() , , , async_read .

:

void handler(...) {
    if (!error) {
      // do your work
      boost::asio::async_read(fifo, buffer, handler); // <-- at the end of the handler a subsequent async_read is put to the ioservice, so it never goes out-of-work
    }
}

boost::asio::io_service io_service;
int fifo_d = open("/tmp/fifo", O_RDONLY);
boost::asio::posix::stream_descriptor fifo(io_service, fifo_d);
boost::asio::async_read(fifo, buffer, handler); // <-- you call async_read only once here.
io_service.run(); //<-- this blocks till an error occurs
0

Source: https://habr.com/ru/post/1624911/


All Articles