Search code examples
c++named-pipesfstreamifstream

Open an ifstream on a pipe with no data without blocking


I am trying to use an ifstream to open a named pipe that will eventually have data written to it.

std::cout << "Opening " << name << std::endl;
std::ifstream manual_shutdown_file(name.c_str());
std::cout << "Opened " << name << std::endl;

When I run the program, it blocks in the ifstream constructor. I see "Opening name" printed to the console, but the opened statement does not appear.

I know that I am connecting to the pipe, because if I execute

$ echo foo > name

from a shell, then the constructor returns and the Opened statement is printed. Is there no way to open a pipe until it has data in it, even if I do not want to immediately try reading it?


Solution

  • Calling open on the read end of a pipe will block until the write end is opened.

    You can use the O_NONBLOCK flag to open the file descriptor for the pipe, but there is no standard way to then use the fd with std::ifstream, see here.

    Guessing at your requirement, I'd say a small class that opens the fd and presents a polling signal interface would suit, something like:

    namespace blah
    {
    class signal_t
    {
    private:
       int fd;
    
       // note: define sensible copy/move semantics
       signal_t(const signal_t&) = delete;
       signal_t& operator=(const signal_t&) = delete;
    public:
       signal_t(const char* named_pipe);   // open fd, set O_NONBLOCK
    
       void notify() const;                // write 1 byte to fd as signal
       bool poll() const;                  // attempt to read from fd, return true if signalled.
    
       ~signal_t();                        // close fd
    };
    }