Description
I tripped onto some odd behaviour.
I was under the assumption calling File::open()
on a directory would Err(), and that I could use that to handle a user specifying a path that was not a file, ( instead of falling prey to race conditions by stat-ing first and then opening second ).
However, ... bad things happened instead.
use std::path::PathBuf;
use std::fs::File;
use std::io::BufRead;
use std::io::BufReader;
fn main() {
let file = File::open(PathBuf::from("/tmp")).unwrap();
let buf = BufReader::with_capacity(100, file);
let _lines: Vec<std::io::Result<String>> = buf.lines().collect();
}
The last of these lines will run forever, with strace reporting:
read(3, 0x564803253b80, 100) = -1 EISDIR (Is a directory)
Over and over again ad-infinitum with no end in sight.
Somehow I had a variation of this go crazy and eat 200% of my ram, but I'm having a hard time reproducing that exact case (Though it may have been related to the target-directory in question also being massive in my case).
Digging shows related bug #43504
The profound question that remains unanswered is: "Why is calling File::open on a directory fine?"
And the residual question is "How does one invoke File::open in such a way that it refuses to work on directories".
And importantly, how do I achieve that portably?
And if none of these concerns can be mitigated, the very least that could be done is have this giant foot-gun documented somewhere in File::open
.
( As far as I can divine, there's no useful behaviour to be found by allowing File::open to work on directories, as standard read() semantics simply don't work on directory filehandles, you have to use readdir() )