Open an ifstream on a pipe with no data without blocking
Asked Answered
B

3

6

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?

Brambling answered 4/3, 2013 at 23:18 Comment(0)
L
2

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
};
}
Lacey answered 5/3, 2013 at 0:35 Comment(0)
L
0

Since opening an input pipe via ifstream blocks until there is someone writing to it, you could always just let the ifstream block. Then to unblock it from another thread create your own ofstream to that same pipe then immediately close the ofstream. This will unblock the ifstream and have it marked with eof. This is much easier and less error prone than messing with the platform specific controls of the file handles.

Landgravine answered 6/8, 2020 at 1:27 Comment(0)
I
-1

You actually can open a std::ifstream on a named pipe without blocking for a writer, but you must set the flags as though you were also going to write to the stream.

Try std::ifstream pipe_stream(filename, std::ifstream::in | std::ifstream::out), or stream.open(filename, std::ifstream::in | std::ifstream::out).

Indign answered 10/3, 2016 at 23:58 Comment(1)
From man 3 open "O_RDWR Open for reading and writing. The result is undefined if this flag is applied to a FIFO." I guess in c++ opening a file in read & write mode will do the same thingGebelein

© 2022 - 2025 — McMap. All rights reserved.