-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use AsFd
and AsSocket
instead of AsRawFd
and AsRawSocket
#38
Comments
If we do this, it would be a breaking change because it would change types that implement |
I agree, this might be premature. Let's wait until the ecosystem evolves to act. |
work-around for smol-rs/polling#38 breaking namada tooling build with nightly 2022-05-20
work-around for smol-rs#38 breaking namada tooling build with nightly 2022-05-20
work-around for smol-rs/polling#38 breaking namada tooling build with nightly 2022-05-20
Okay, the ecosystem has evolved. We can now definitely use |
Unfortunately I can't escape the conclusion that integrating I/O safety into this API would require it becoming either unsafe or very unwieldy. For any given |
To clarify this issue: the Therefore a file descriptor must be unregistered before it is dropped to prevent soundness issues. The idea was to have a struct Bad {
x: Option<TcpStream>,
y: TcpStream,
}
impl AsFd for Bad {
fn as_fd(&self) -> BorrowedFd<'_> {
self.x.as_ref().unwrap_or(&self.y).as_fd()
}
} Then a user could do: let bad = Bad { .. };
let mut bad: Source<Bad> = poller.register(bad, ..);
bad.get_mut().x = None;
drop(bad); This means that This could be solved by marking I'm not sure if there is an actual solution to this aside from just making the public API as it currently is unsafe and then letting higher level crates be the explicit safe interface. |
@smol-rs/admins @sunfishcode We should brainstorm about this problem. I really don't want to remove the |
well, if it is unsafe to use, just make it unsafe and document the requirement that the file descriptor must be stable. |
If we make direct access to the underlying source unsafe, several other operations also become unsafe, like |
hm we could implement some guarding in the |
This might be the best solution, but what should happen //if// the check doesn't match? The only real option would be to |
I just realized this probably wouldn't work. Consider the following code: let poller = Arc::new(Poller::new());
let (signal, cont) = mpsc::channel();
// on main thread
struct Bad(Option<TcpStream>);
impl AsFd for Bad {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_ref().unwrap().as_fd()
}
}
let mut source = poller.add(Bad(Some(TcpStream::connect(..))));
source.with_mut(|bad| {
// Drop the inner TCP socket, closing the FD.
bad.0 = None;
// Signal the other thread and block forever.
signal.send(()).unwrap();
parking::Parker::new().park();
unreachable!()
});
// on thread #2
cont.recv().unwrap();
// Allocate a new file descriptor. This probably takes up the previously
// allocated socket's FD.
let _unaware = TcpStream::connect(..);
// This call arbitrarily uses the closed/new socket, immediately leading to undefined behavior.
poller.wait(..)?; The problem being that there's nothing really stopping us from parking mid-closure and then doing unsound things in the meantime. This could be solved by having a mutex somewhere that doesn't let One solution would be to make See tokio-rs/mio#1588 for the mirrored |
I unfortunately don't have any answers here. Since kqueue uses file descriptor associations, rather than file description associations, I/O safety would oblige |
I'm not sure I understand why kqueue is a safety concern here? If a file descriptor added to a kqueue is closed, it is automatically removed from the kqueue. In contrast with epoll, which will still get events after the fd is closed, with the fd number of the closed fd. Neither behavior is inherently unsafe, though I don't know if thats an issue with how it is used in
Theoretically there are a few safe options:
I don't think any of these are viable with how the library would normally be used. Though higher level libraries using |
I also think this affects Solaris' event ports, but I can't be bothered to take a deep dive into illumos' source code to figure it out. Some Solaris nerd can tell me if I'm wrong.
Sounds good to me. |
Closed in #123 |
Rust 1.63 stabilized the I/O safety features in the standard library. As per sunfishcode/io-lifetimes#38, Rust crates in the ecosystem (such as
async-std
andsmol
) should be migrated to using the new I/O-safe traits instead of theAsRaw*
family of traits.To port this crate, we could replace the
Source
trait implementations, currently:with this:
Although, ideally, the trait would return
BorrowedFd<'_>
instead, and the rest of the crate would be adjusted accordingly.I am willing to implement this change in this crate as well as in
async-io
. The main question is if the MSRV bump is worth it.The text was updated successfully, but these errors were encountered: