Async-std: TcpListener::incoming fails to receive new connections

Created on 28 Sep 2020  路  7Comments  路  Source: async-rs/async-std

Based on this question, it appears that there is some issue with the incoming stream on TcpListener.

use async_std::net::TcpListener;
use futures::StreamExt;

#[async_std::main]
async fn main() {
    let listener = TcpListener::bind("127.0.0.1:4444").await.unwrap();
    println!("Server listening on {}", listener.local_addr().unwrap());

    listener
        .incoming()
        .for_each(|tcpstream| async move {
            let tcpstream = tcpstream.unwrap();
            println!("Accepting from: {}", tcpstream.peer_addr().unwrap());
        })
        .await;
}
[dependencies]
async-std = { version = "=1.6.4", features = ["attributes"] }
futures = "0.3"

This example does not print anything when new connections are made to that TcpListener, e.g. with nc 127.0.0.1 4444. My guess is that it is somehow failing to send notifications to the waker.

It works when fine rewritten to use accept in a loop.

Most helpful comment

[email protected] has been published with a fix!

All 7 comments

I believe that this affects Tide as well, as we tried Tide a couple of days ago and it worked well, but no one in our team (Mac & Linux) can make it work today. It keeps frozen on accepting the connection:

   Compiling port-http v0.1.0 ([[REDACTED]])
    Finished dev [unoptimized + debuginfo] target(s) in 3.34s
     Running `target/debug/port-http`
tide::log Logger started
    level TRACE
port_http::http::router Test1
tide::server Adding middleware tide::cookies::middleware::CookiesMiddleware
tide::server Adding middleware tide::log::middleware::LogMiddleware
async_io::driver main_loop: sleeping for 1000 us
port_http::http::router Test2
polling::epoll insert: epoll_fd=3, fd=7
tide::listener::tcp_listener Server listening on http://127.0.0.1:8080
polling::epoll interest: epoll_fd=3, fd=7, ev=Event { key: 1, readable: true, writable: false }
async_io::driver block_on: notified
async_io::reactor process_timers: 0 ready wakers
polling Poller::wait(_, Some(0ns))
polling::epoll wait: epoll_fd=3, timeout=Some(0ns)
polling::epoll interest: epoll_fd=3, fd=5, ev=Event { key: 18446744073709551615, readable: true, writable: false }
polling::epoll new events: epoll_fd=3, res=0
polling::epoll interest: epoll_fd=3, fd=4, ev=Event { key: 18446744073709551615, readable: true, writable: false }
async_io::reactor react: 0 ready wakers
polling::epoll interest: epoll_fd=3, fd=7, ev=Event { key: 1, readable: true, writable: false }
async_io::driver block_on: waiting on I/O
async_io::reactor process_timers: 0 ready wakers
polling Poller::wait(_, Some(599.990063236s))
polling::epoll wait: epoll_fd=3, timeout=Some(599.990063236s)
polling::epoll interest: epoll_fd=3, fd=5, ev=Event { key: 18446744073709551615, readable: true, writable: false }
async_io::driver main_loop: sleeping for 2500 us
async_io::driver main_loop: sleeping for 5000 us
async_io::driver main_loop: sleeping for 10000 us
polling::epoll new events: epoll_fd=3, res=1
polling::epoll interest: epoll_fd=3, fd=4, ev=Event { key: 18446744073709551615, readable: true, writable: false }
async_io::reactor react: 0 ready wakers
async_io::driver block_on: stops hogging the reactor
async_io::driver main_loop: waiting on I/O
async_io::reactor process_timers: 0 ready wakers
polling Poller::wait(_, Some(585.727612537s))
polling::epoll wait: epoll_fd=3, timeout=Some(585.727612537s)
polling::epoll interest: epoll_fd=3, fd=5, ev=Event { key: 18446744073709551615, readable: true, writable: false }

Same for me. Reverting from async-std 1.6.4 to 1.6.3 fixed it

Hi, thanks for the report! I think there may be one of two causes for the issue here:

We should probably dig deeper and find out what's going on.

Taking a look at this impl, it seems like it's calling accept, then dropping the future. My guess is that the new async-io release makes accept's future remove the registered waker in the destructor of the future.

https://github.com/async-rs/async-std/blob/e8126633a89aafea23259eb9faddb70b89f94423/src/net/tcp/listener.rs#L188-L198

In fact, async-io has had a commit with the message Unregister wakers if readable() or writable() is canceled since the latest release, so it sounds likely to me.

@Darksonn can you file an issue on async-io about this? This doesn't seem like it should have been a patch release.

Though we can probably duplicate the AsyncRead impl from async_net::TcpStream to fix async-std's impl. Unfortunate, but that way we don't need to wait for a fix in async-io.

[email protected] has been published with a fix!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

95th picture 95th  路  7Comments

imtsuki picture imtsuki  路  5Comments

yoshuawuyts picture yoshuawuyts  路  6Comments

matthewrobertbell picture matthewrobertbell  路  7Comments

yoshuawuyts picture yoshuawuyts  路  3Comments