Since files and streams are closed automatically when being dropped, but io::stdin()
only providing a handle to the underlying stream, I fail to see how to explicitly close stdin
or stdout
or detect EOF on stdin
in my program.
Consider
fn main() {
let mut stdin = io::stdin();
let mut linebuffer = String::new();
loop {
match stdin.read_line(&mut linebuffer) {
Ok(i) if i == 0 => { break; },
Ok(i) => {
println!("{} {}", linebuffer, i);
},
Err(e) => { panic!(e); }
}
linebuffer.clear();
}
}
Checking the number of bytes put into the buffer seems flaky because the pipe might get flushed with zero bytes having being written to it. Reading from a closed stdin
should cause an IOError
, but it doesn't.
Somewhat related to that: How to explicitly close my own stdout
/ stderr
?
Some time ago there was ErrorKind::EndOfFile
enum variant which was emitted upon a read operation when the source stream is closed. It seems that it didn't get to the new I/O library implementation, and instead Read
trait has been changed to return 0 read bytes upon EOF. And indeed, this is specified in I/O reform RFC. So yes, checking for zero is a valid way to detect end of stream in the current Rust.
By the way, you can write Ok(0)
instead of Ok(i) if i == 0
:
match stdin.read_line(&mut buf) {
Ok(0) => break,
...
}
As for how to close stdout()
/stderr()
, it seems that the current API does not provide a way to do it, unfortunately. It is probably a feature worth an RFC or at least an RFC issue.
Regarding my own sub-question on how to close stdout/stderr: The correct way is to use the wait- or the wait_with_output-method on a process::Child
. Both methods close the subprocess's stdin before waiting for it to quit, eliminating the possibility of a deadlock between both processes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With