我正在使用Boost.ASIO读取标准输入,但是当我输入它时,我希望在输入完全消耗时管道会关闭。即我在服务线上这样做:
cat somefile.txt | myprog
我希望myprog
会看到文件关闭。相反,它会永远等待。
代码如下所示:
boost::asio::posix::stream_descriptor as_stdin(ios);
{
boost::system::error_code error;
as_stdin.assign(dup(STDIN_FILENO), error);
if ( error ) {
exit(2);
}
}
auto proc = [&as_stdinr](auto yield) {
boost::asio::streambuf buffer;
while ( as_stdin.is_open() ) {
auto bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield);
if ( bytes ) {
buffer.commit(bytes);
std::istream in(&buffer);
std::string line;
std::getline(in, line);
std::cerr << line << std::endl;
} else {
std::cerr << "No bytes read" << std::endl;
}
}
std::cerr << "Done" << std::endl;
};
boost::asio::spawn(ios, proc);
所有文件内容都被正确回显,因此从管道读取工作正常,但没有&#34;没有字节读取&#34;或者&#34;完成&#34;消息永远打印出来。无论有没有dup
系统调用,我都试过了。
我误解了管道是如何工作的,还是我做错了什么或丢失了别的东西?
我认为这归结为&#34;如何在使用协同程序时检测EOF?&#34;
答案 0 :(得分:1)
您可以从async_read_until
中捕获异常size_t bytes = 0;
bool eof = false;
try {
bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield);
} catch(std::exception const& e) {
std::cerr << "Exception: " << e.what() << "\n";
bytes = 0;
eof = true;
}
// ...
if (eof) break;
或使用error_code:
boost::system::error_code ec;
auto bytes = boost::asio::async_read_until(as_stdin, buffer, '\n', yield[ec]);
// ...
if (ec) {
std::cerr << "Error: " << ec.message() << "\n";
break;
}
两种情况下的输出非常相似
Exception: End of file
No bytes read
Done
或者
No bytes read
Error: End of file
Done
常规文件不能与POSIX stream_descriptor一起使用,请参阅https://stackoverflow.com/a/23631715/85371