In this simple example of Boost.Process 0.5 ( http://www.highscore.de/boost/process0.5/index.html) the output of a program (ls
) is feeding a stream. The stream works fine but contrary to the expectation the stream doesn't become invalid (e.g. end-of-stream) after the program finishes (similar to previous version of Boost.Process, e.g. http://www.highscore.de/boost/process/index.html)
What am I missing in order to make the stream (is
in the example) automatically invalid after child program exits?
Perhaps is it an option that I have to set in the Boost.Streams stream
of file_descriptor
?
#include <boost/process.hpp> // version 0.5 from http://www.highscore.de/boost/process0.5/process.zip
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <string>
using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
int main(){
boost::process::pipe p = create_pipe();
file_descriptor_sink sink(p.sink, close_handle);
child c = execute(run_exe("/usr/bin/ls"), bind_stdout(sink));
file_descriptor_source source(p.source, close_handle);
stream<file_descriptor_source> is(source);
std::string s;
while(std::getline(is, s)){
std::cout << "read: " << s << std::endl;
}
std::clog << "end" << std::endl; // never reach
}
I had a private (actually through Nabble) communication with Boris Schaeling, the author of the library. After discarding several possibilities, like bugs in posix/boost.iostreams, he gave me a slight modification of the code that works. Basically, what I can deduce is that the
file_descriptor sink
must be out of scope (destroyed) in order for the stream to return an EOF. The working code simply adds a specific scope forsink
(listed at the end). I think this makes easy to encapsulate all in apistream
kind of class. (Next step in my list will be to allow also output to the process.)Works with Boost 1.48 (Fedora 17).
Compiles with
c(lang)++ -lboost_system -lboost_iostreams
EDIT: This seems to work as well, which avoid the artificial scope, but can be confusing because the sink has to be a temporary:
This works on POSIX-like systems:
Note that it handles SIGCHLD to asynchronously set
status
. It was taken from http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.starting_a_program. This page also shows the Windows style of doing the same: