read_key goes into an endless loop and eventually exhausts file handles
mitsuhiko opened this issue · 2 comments
mitsuhiko commented
Minimal repo case:
use console::Term;
fn main() {
eprintln!("Press any key to exist");
Term::stderr().read_key().unwrap();
}
If this script is compiled and run with a close stdin (cat | target/debug/repro
) it will fail with
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 24, kind: Uncategorized, message: "Too many open files" }'
The issue is that read_single_key
has a condition where it will call back into itself recursively.
Refs astral-sh/rye#184
mitsuhiko commented
The broken logic seems to be read_single_char
or other poll uses. Changing it into a basic libc::read
makes it work
fn read_single_char(fd: i32) -> io::Result<Option<char>> {
let mut buf = [0u8; 20];
let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, 20) };
return if read < 0 {
Err(io::Error::last_os_error())
} else {
Ok(Some(buf[0] as char))
};
}
read_single_char
is non blocking in console at the moment. The blocking part is in the None
condition of the read_single_char
result and I presume this does not correctly block.
I'm guessing that this entire polling business does not really work.