nix
nix copied to clipboard
FdSet: allow conversion from iterable of AsFd
What does this PR do
Adds an implementation of FromIterator
and From
for FdSet
, allowing them to be constructed from iterables of types that implement AsFd
.
Checklist:
- [X] I have read
CONTRIBUTING.md
- [X] I have written necessary tests and rustdoc comments
- [X] A change log has been added if this PR modifies nix's API
I'm not sure what the better type is, but I think the iterator item type should be the same as the argument type ofFdSet::insert, so that the implementation would be just
for fd in iter.into_iter() {
result.insert(fd)
}
instead of duplicating the unsafe implementation of insert.
would that be ok: https://github.com/nix-rust/nix/commit/7def327db8683ca31f8e684390b21675ac7fd5e5 ?
Or would it be an API breaking change to also change insert?
The goal here was definitely to avoid having to add a map in the user's construction code. What if we factored the unsafe code into another function that both insert and this could use?
src/poll.rs
has a comment why BorrowedFd
is used as argument type instead f F: AsFd
, which also applies here, I think:
https://github.com/nix-rust/nix/blob/f129095ac6e76505cfa6711cc78e2b5f4430070e/src/poll.rs#L41
AsFd would allow passing an OwnedFd or File, which would be closed on drop, leaving the FdSet with closed fds.
you can reproduce it if you change your test a bit
fn test_fdset_from_iterable() {
let (r1, w1) = pipe().unwrap();
let (r2, w2) = pipe().unwrap();
let reads = [r1, r2]
.into_iter()
.map(|fd| (fd.as_raw_fd(), fd))
.collect::<std::collections::HashMap<_, _>>();
let writes = [w1, w2];
let reads_fdset: FdSet = reads.values().into();
let writes_fdset: FdSet = writes.into();
for w in writes_fdset.fds(None) {
nix::unistd::write(w, b"x").expect("should work");
}
/// ...
}
panics with EBADF
.
The FdSet
interfaces indeed have a reason why they are using BorrowedFd
rather than Fd: AsFd
, see this PR
And for that unsafe
code snippet,
unsafe { libc::FD_SET(fd.as_raw_fd(), &mut result.set) };
I am not sure I understand what this means,
The goal here was definitely to avoid having to add a map in the user's construction code.
would you like to elaborate on it a bit?
The
FdSet
interfaces indeed have a reason
we might document it :)
appart from type issue, I like the idea of the PR: having a way to construct an FdSet
from an iterable!
The
FdSet
interfaces indeed have a reasonwe might document it :)
Yeah, I think we can document it in the comments
would you like to elaborate on it a bit?
The goal was to avoid this snippet from the linked commit: writes.iter().map(|x| x.as_fd()).into()
I have not forgotten this PR, I am simply sidetracked onto other projects for a bit :)