-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
net: use &self with TcpListener::accept #2919
Changes from all commits
4889d97
794d357
40af6af
4fa7182
b498b04
a8fed9b
7164656
5b21c0a
8601368
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,8 +132,19 @@ impl Registration { | |
cfg_io_readiness! { | ||
impl Registration { | ||
pub(super) async fn readiness(&self, interest: mio::Interest) -> io::Result<ReadyEvent> { | ||
// TODO: does this need to return a `Result`? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It turns out that it does need to return a result :) This implementation is not great but I believe the shutdown logic needs to be revisited post 0.3. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tracked my thoughts in #2924 |
||
Ok(self.shared.readiness(interest).await) | ||
use std::future::Future; | ||
use std::pin::Pin; | ||
|
||
let fut = self.shared.readiness(interest); | ||
pin!(fut); | ||
|
||
crate::future::poll_fn(|cx| { | ||
if self.handle.inner().is_none() { | ||
return Poll::Ready(Err(io::Error::new(io::ErrorKind::Other, "reactor gone"))); | ||
} | ||
|
||
Pin::new(&mut fut).poll(cx).map(Ok) | ||
}).await | ||
} | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,5 @@ | ||
use crate::future::poll_fn; | ||
use crate::io::PollEvented; | ||
use crate::net::tcp::{Incoming, TcpStream}; | ||
use crate::net::tcp::TcpStream; | ||
use crate::net::{to_socket_addrs, ToSocketAddrs}; | ||
|
||
use std::convert::TryFrom; | ||
|
@@ -40,7 +39,7 @@ cfg_tcp! { | |
/// | ||
/// #[tokio::main] | ||
/// async fn main() -> io::Result<()> { | ||
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await?; | ||
/// let listener = TcpListener::bind("127.0.0.1:8080").await?; | ||
/// | ||
/// loop { | ||
/// let (socket, _) = listener.accept().await?; | ||
|
@@ -171,7 +170,7 @@ impl TcpListener { | |
/// | ||
/// #[tokio::main] | ||
/// async fn main() -> io::Result<()> { | ||
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await?; | ||
/// let listener = TcpListener::bind("127.0.0.1:8080").await?; | ||
/// | ||
/// match listener.accept().await { | ||
/// Ok((_socket, addr)) => println!("new client: {:?}", addr), | ||
|
@@ -181,18 +180,25 @@ impl TcpListener { | |
/// Ok(()) | ||
/// } | ||
/// ``` | ||
pub async fn accept(&mut self) -> io::Result<(TcpStream, SocketAddr)> { | ||
poll_fn(|cx| self.poll_accept(cx)).await | ||
pub async fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { | ||
let (mio, addr) = self | ||
.io | ||
.async_io(mio::Interest::READABLE, |sock| sock.accept()) | ||
.await?; | ||
|
||
let stream = TcpStream::new(mio)?; | ||
Ok((stream, addr)) | ||
} | ||
|
||
/// Polls to accept a new incoming connection to this listener. | ||
/// | ||
/// If there is no connection to accept, `Poll::Pending` is returned and | ||
/// the current task will be notified by a waker. | ||
pub fn poll_accept( | ||
&mut self, | ||
cx: &mut Context<'_>, | ||
) -> Poll<io::Result<(TcpStream, SocketAddr)>> { | ||
/// If there is no connection to accept, `Poll::Pending` is returned and the | ||
/// current task will be notified by a waker. | ||
/// | ||
/// When ready, the most recent task that called `poll_accept` is notified. | ||
/// The caller is responsble to ensure that `poll_accept` is called from a | ||
/// single task. Failing to do this could result in tasks hanging. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should eventually include language that |
||
pub fn poll_accept(&self, cx: &mut Context<'_>) -> Poll<io::Result<(TcpStream, SocketAddr)>> { | ||
loop { | ||
let ev = ready!(self.io.poll_read_ready(cx))?; | ||
|
||
|
@@ -293,46 +299,6 @@ impl TcpListener { | |
self.io.get_ref().local_addr() | ||
} | ||
|
||
/// Returns a stream over the connections being received on this listener. | ||
/// | ||
/// Note that `TcpListener` also directly implements `Stream`. | ||
/// | ||
/// The returned stream will never return `None` and will also not yield the | ||
/// peer's `SocketAddr` structure. Iterating over it is equivalent to | ||
/// calling accept in a loop. | ||
/// | ||
/// # Errors | ||
/// | ||
/// Note that accepting a connection can lead to various errors and not all | ||
/// of them are necessarily fatal ‒ for example having too many open file | ||
/// descriptors or the other side closing the connection while it waits in | ||
/// an accept queue. These would terminate the stream if not handled in any | ||
/// way. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ```no_run | ||
/// use tokio::{net::TcpListener, stream::StreamExt}; | ||
/// | ||
/// #[tokio::main] | ||
/// async fn main() { | ||
/// let mut listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); | ||
/// let mut incoming = listener.incoming(); | ||
/// | ||
/// while let Some(stream) = incoming.next().await { | ||
/// match stream { | ||
/// Ok(stream) => { | ||
/// println!("new client!"); | ||
/// } | ||
/// Err(e) => { /* connection failed */ } | ||
/// } | ||
/// } | ||
/// } | ||
/// ``` | ||
pub fn incoming(&mut self) -> Incoming<'_> { | ||
Incoming::new(self) | ||
} | ||
|
||
/// Gets the value of the `IP_TTL` option for this socket. | ||
/// | ||
/// For more information about this option, see [`set_ttl`]. | ||
|
@@ -390,10 +356,7 @@ impl TcpListener { | |
impl crate::stream::Stream for TcpListener { | ||
type Item = io::Result<TcpStream>; | ||
|
||
fn poll_next( | ||
mut self: std::pin::Pin<&mut Self>, | ||
cx: &mut Context<'_>, | ||
) -> Poll<Option<Self::Item>> { | ||
fn poll_next(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> { | ||
let (socket, _) = ready!(self.poll_accept(cx))?; | ||
Poll::Ready(Some(Ok(socket))) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes here solve a potential deadlock during shutdown. Waking a task must be done from outside of the lock or it could result in a deadlock due to an attempt to re-enter the lock.