2

So... I start another process that accepts some input from my program (it could go the other way around too). Something of the sort:

FILE *f(popen("sendmail", "w"));

Now, I can put f in an fstream so that way I can just use the stream (since my program is in C++, it seems to be a sensible thing to do.)

std::ofstream output(fileno(f));
...
output << "To: santa.claus@example.com" << std::endl;
...

Up to here, I'm good. Now comes the point where I'm done sending data to the child process. All I want is to close the pipe. From what I know, we are expected to use pclose() because that function ensures that the other process receives all the data. In otherwise words, the pclose() function knows how to cleanly severe a pipe.

Unfortunately, since I put f in an ofstream, I cannot just close it, can I?

pclose(f); // proper way to close a pipe
...
ofstream::~ofstream() { ... close(fd); ... } // not the right way to close a pipe

Is there a way to capture the close from the ofstream and ensure it closes the way I want it to eb closed.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • 1
    I believe this could help you in some way: http://stackoverflow.com/a/1105009/2428958 Also, you might want to consider deriving streambuf and implementing your own stream class instead of using std::ofstream in this case - since you cannot attach a custom "close" to the destructor. – Mateusz Kołodziejski Jan 22 '14 at 07:39
  • The same code that opened the pipe should close it. I'd suggest associating the pipe with a class whose destructor closes the pipe. You don't need to capture the close -- you can do the close when the object is destroyed. – David Schwartz Jan 22 '14 at 22:18
  • @MateuszKołodziejski, That's the perfect answer, may you want to write an actual answer? (although the link did not really help, but deriving from streambuf is what I need to do.) – Alexis Wilke Jan 22 '14 at 22:51

1 Answers1

1

I would inherit a custom class from ofstream:

class PipeStream : public std::ofstream

and overwrite destructor

PipeStream::~PipeStream { pclose(f) };

so that pclose(f) is run before fclose(f)?

Manex
  • 528
  • 4
  • 15
  • That could be a problem if you want to catch the close() call and it's not virtual, right? Since std::ofstream is a template, I'm not 100% sure how that works, but I would think that's the same as usual classes so someone using just an ofstream could call the wrong close() function... – Alexis Wilke Jan 22 '14 at 22:02