Reputation: 2300
I'm reading stdin using Boost.ASIO, but when I pipe into it I would expect that the pipe would close when the input has been fully consumed. I.e. I'm doing this at the commmand line:
cat somefile.txt | myprog
And I'd expect that myprog
will see the file close. Instead it waits forever.
The code looks like this:
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);
All of the file content is properly echoed, so reading from the pipe works fine, but neither of the "No bytes read" or "Done" messages are ever printed. I've tried both with and without the dup
system call.
Am I misunderstanding how the pipe works, or am I doing something wrong or missing something else?
I think this comes down to "How do I detect EOF when using coroutines?"
Upvotes: 1
Views: 447
Reputation: 393174
You could catch the exception from 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;
Or use the 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;
}
Output is very similar in both cases
Exception: End of file
No bytes read
Done
Or
No bytes read
Error: End of file
Done
Regular files cannot be used with POSIX stream_descriptor, see https://stackoverflow.com/a/23631715/85371
Upvotes: 1