-
Notifications
You must be signed in to change notification settings - Fork 735
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
Remove Guarantee to Deregister on Drop #753
Comments
Given that epoll itself does not make this guarantee (if the FD is duped, epoll only deregisters once all the dups have been dropped), I think that it would be reasonable to require manual calls to |
I don't think this can be done backwards compatibly, as tokio-rs/tokio-core#275 shows external code in the wild at least is relying on on the behavior that drop is equivalent to deregistration. Put another way, Tokio shouldn't have to call some APIs, for example, to avoid memory leaks. Any drop of an I/O object (abnormal via panics or normal via returning in a function) should clean up all resources, including those transitively associated with an instance of |
@alexcrichton it's definitely a breaking change to mio, but IMO it's worth it since it prevents extra signals from epoll, and prevents the Fuchsia and Windows |
w.r.t. epoll, the first drop actually prevents the fd from every truly being deregistered. Drop closes the underlying fd, whereas deregister explicitly calls epoll_ctl(fd, del...) (see https://github.com/carllerche/mio/blob/e73a6489ddddfa618388f5ccd86d1fa346600b7b/src/sys/unix/epoll.rs#L137) For some demonstrating code, see: extern crate mio;
extern crate libc;
use std::io::{self, Write};
use std::os::unix::io::{RawFd, FromRawFd};
use std::fs::File;
use mio::*;
use mio::unix::EventedFd;
fn pipe() -> io::Result<(RawFd, RawFd)>{
let flags = libc::O_NONBLOCK | libc::O_CLOEXEC;
let mut pipes = [0; 2];
unsafe {
if -1 == libc::pipe2(pipes.as_mut_ptr(), flags) {
return Err(io::Error::last_os_error());
}
}
Ok((pipes[0], pipes[1]))
}
fn main() {
let (rfd, wfd) = pipe().unwrap();
let mut wf = unsafe { File::from_raw_fd(wfd) };
wf.write(b"a").unwrap();
let r_tok = 0;
let poll = Poll::new().unwrap();
poll.register(&EventedFd(&rfd), Token(r_tok), Ready::readable(), PollOpt::level()).unwrap();
let rfd2 = unsafe { libc::dup(rfd) };
unsafe { libc::close(rfd) };
let mut events = Events::with_capacity(1024);
poll.poll(&mut events, None).unwrap();
for event in events.iter() {
println!("{:?}", event.token());
}
} So, to be truly correct and cover |
@cramertj all this is doing though is moving the |
Sorry, to clarify: the first drop only prevents deregistration if the fd has already been duplicated. If there is no duplicate, the underlying fd close does deregister from epoll automatically. |
@alexcrichton Oh, because |
@cramertj ah yeah today it would be very difficult to do but with tokio-rs/tokio-rfcs#3 you only need a |
@alexcrichton Okay! I think it seems reasonable to just wait for the new version of tokio then, depending on how far away you think that is (I'm imagining <6 months or so? Is that too ambitious? Probably). |
@cramertj given that this would require a v0.7 bump, it will be a bit tricky. Tokio exposes Given that |
@carllerche Yeah, it seems like we're building up a cascade of breaking changes across |
That said, I think we would have to say something like dropping a handle (fd backed value) without calling Specifically, This is basically epoll's behavior out of the box, so it seems fine to define Mio the same. |
Making this change would "solve" #361. |
Mio will be requiring `deregister` to be called explicitly in order to guarantee that Poll releases any state associated with the I/O resource. See tokio-rs/mio#753. This patch adds an explicit `deregister` function to `Registration` and updates `PollEvented` to call this function on drop. `Registration::deregister` is also called on `PollEvented::into_inner`. Closes #168
Mio will be requiring `deregister` to be called explicitly in order to guarantee that Poll releases any state associated with the I/O resource. See tokio-rs/mio#753. This patch adds an explicit `deregister` function to `Registration` and updates `PollEvented` to call this function on drop. `Registration::deregister` is also called on `PollEvented::into_inner`. Closes #168
On master |
In the documentation for
Poll
there's a note that "Evented handles are automatically deregistered when they are dropped. It is common to never need to explicitly call deregister." If deregistration requires access to the selector, implementing this guarantee requires thatEvented
implementations keep aWeak<Selector>
or similar. Especially in the case of event loops such as tokio-core, it doesn't seem too burdensome to require that they manually deregisterEvented
s prior to dropping them. Changing this guarantee would allow for more efficientEvented
implementation.The text was updated successfully, but these errors were encountered: