在Boost.Process 0.5(http://www.highscore.de/boost/process0.5/index.html)的这个简单示例中,程序(ls
)的输出正在为流提供数据。流工作正常但与预期相反,流程在程序完成后不会变为无效(例如,流末尾)(类似于以前版本的Boost.Process,例如http://www.highscore.de/boost/process/index.html)
在子程序退出后,为了使流(示例中的is
)自动无效,我缺少什么?
也许我必须在stream
的Boost.Streams 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
}
答案 0 :(得分:4)
我与图书馆的作者Boris Schaeling进行了私人(实际上是通过Nabble)的沟通。抛弃了几种可能性,比如posix / boost.iostreams中的bug,他给了我一些有效的代码修改。基本上,我可以推断出file_descriptor sink
必须超出范围(已销毁)才能使流返回EOF。工作代码只是为sink
添加了一个特定的范围(最后列出)。我认为这很容易将所有类型封装在pistream
类中。 (我的列表中的下一步是允许输出到流程。)
适用于Boost 1.48(Fedora 17)。
#include <boost/process.hpp> // version 0.5
#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() {
pipe p = create_pipe();
{
// note the scope for sink
file_descriptor_sink sink(p.sink, close_handle);
/* child c = */ // not necessary to hold a child object, it seems.
execute(run_exe("/usr/bin/ls"), bind_stdout(sink));
} // note the scope for 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
}
使用c(lang)++ -lboost_system -lboost_iostreams
编辑:这似乎也有效,避免了人为的范围,但可能会让人感到困惑,因为接收器必须是临时的:
...
pipe p = create_pipe();
execute(run_exe("/usr/bin/ls"), bind_stdout(
file_descriptor_sink(p.sink, close_handle)
));
file_descriptor_source source(p.source, close_handle);
...
答案 1 :(得分:3)
这适用于类似POSIX的系统:
#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 <boost/asio.hpp>
#include <string>
using namespace boost::process;
using namespace boost::process::initializers;
using namespace boost::iostreams;
int main()
{
boost::asio::io_service io_service;
int status = 1;
boost::asio::signal_set set(io_service, SIGCHLD);
set.async_wait(
[&status](const boost::system::error_code&, int) { ::wait(&status); }
);
boost::process::pipe p = create_pipe();
file_descriptor_sink sink(p.sink, close_handle);
child c = execute(run_exe("/bin/ls"), bind_stdout(sink));
file_descriptor_source source(p.source, close_handle);
stream<file_descriptor_source> is(source);
std::string s;
while(status && std::getline(is, s))
{
std::cout << "read: " << s << std::endl;
}
std::clog << "end" << std::endl; // never reach
}
请注意,它将SIGCHLD处理为异步设置status
。它取自http://www.highscore.de/boost/process0.5/boost_process/tutorial.html#boost_process.tutorial.starting_a_program。此页面还显示了执行相同操作的Windows样式:
#if defined(BOOST_WINDOWS_API)
DWORD exit_code;
boost::asio::windows::object_handle handle(io_service, c.process_handle());
handle.async_wait(
[&handle, &exit_code](const boost::system::error_code&)
{ ::GetExitCodeProcess(handle.native(), &exit_code); }
);
#endif
io_service.run();