Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 892
Troy Daniels Avatar asked Mar 04 '13 23:03

Troy Daniels


People also ask

Does ifstream need to be closed?

The short answer is NO. By looking into the GCC implementation of fstream, we can see that the destructor of the class does nothing.

Is pipe read blocking?

Read/Write Are Blocking - when a process reads from a named pipe that has no data in it, the reading process is blocked. It does not receive an end of file (EOF) value, like when reading from a file.

Does ifstream open throw an exception?

The exception will be thrown when you encounter the EOF because you set ifstream::failbit as exception mask, at least on Mac OS 10.10 Yesomite. If a file is read when EOF is encountered, ios_base::failbit will be set together with ios_base::eofbit .

What is non blocking IO in C?

Sometimes it's convenient to have I/O that doesn't block i.e we don't want a read call to block on one in case of input from the other. Solution for this is the given function: To specify non-blocking option: #include<fcntl. h> int fd; fcntl(fd, F_SETFL, O_NONBLOCK);


1 Answers

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
};
}
like image 157
mythagel Avatar answered Nov 15 '22 07:11

mythagel