使用Boost.ASIO读取时,stdin管道未关闭

时间:2016-11-13 07:07:16

标签: c++ asynchronous boost boost-asio

我正在使用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;

1 个答案:

答案 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