Version
tokio-shutdown v0.1.0
└── tokio v0.2.21
├── tokio-macros v0.2.5
Platform
Fails on Windows 10 (64 bit), seems ok on Linux (5.0.0-38-generic #41-Ubuntu SMP Tue Dec 3 00:27:35 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux).
Description
With a tokio runtime which has spawned a task with a TcpListener inside I would expect the bound TCP port to be released when the runtime is dropped, but the this doesn't seem to happen (on windows).
I tried this code:
use std::time::Duration;
use tokio::{net::TcpListener, runtime::Runtime, stream::StreamExt};
fn main() {
println!("Start runtime");
{
let rt = Runtime::new().unwrap();
rt.spawn(async {
let mut listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
let mut incoming = listener.incoming();
while let Some(_c) = incoming.next().await {}
});
std::thread::sleep(Duration::from_secs(1));
}
println!("End runtime");
println!("Start runtime");
{
let rt = Runtime::new().unwrap();
rt.spawn(async {
let mut listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
let mut incoming = listener.incoming();
while let Some(_c) = incoming.next().await {}
});
std::thread::sleep(Duration::from_secs(1));
}
println!("End runtime");
}
Expected output:
Start runtime
End runtime
Start runtime
End runtime
Instead got:
Start runtime
End runtime
Start runtime
thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 10048, kind: AddrInUse, message: "Only one usage of each socket address (protocol/network address/port) is normally permitted." }', src\main.rs:23:32
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
End runtime
Was a bit runtime focused in the issue, might not be relevant. Noticed that this would give the same error (AddrInUse) on Windows (but not Linux):
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
drop(listener);
let listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
drop(listener);
}
While the sync version doesn't panic on either Linux or Window:
use std::net::TcpListener;
fn main() {
let listener = TcpListener::bind("127.0.0.1:1999").unwrap();
drop(listener);
let listener = TcpListener::bind("127.0.0.1:1999").unwrap();
drop(listener);
}
I believe this should be fixed when we upgrade to mio 0.7. The problem is on windows, tokio maps ops to IOCP which are completion based.
Could some check if this is still an issue on master?
I've executed the below snippet (which typically panics in the first 3 rounds with tokio 0.2.22) using master (60d81bb) for some time now and haven't failed yet after ~4M rounds or so.
use tokio::net::TcpListener;
#[tokio::main]
async fn main() {
let mut c = 0;
loop {
println!("Round {}", c);
let _listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
c += 1;
}
}
So as far as I can tell it's solved. Good work and thanks! 💯
I also tried it with this snippet, which does not panic either.
use std::time::Duration;
use tokio::{net::TcpListener, runtime::Runtime, stream::StreamExt};
fn main() {
println!("Start runtime");
{
let rt = Runtime::new().unwrap();
rt.spawn(async {
let mut listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
loop {
let _ = listener.accept().await.unwrap();
}
});
std::thread::sleep(Duration::from_secs(1));
}
println!("End runtime");
println!("Start runtime");
{
let rt = Runtime::new().unwrap();
rt.spawn(async {
let mut listener = TcpListener::bind("127.0.0.1:1999").await.unwrap();
loop {
let _ = listener.accept().await.unwrap();
}
});
std::thread::sleep(Duration::from_secs(1));
}
println!("End runtime");
}
I'm closing the issue.
Actually, I ran it on Linux and the issue doesn't exist here in the first place.
@oll3 Did you run it on windows?
Actually, I ran it on Linux and the issue doesn't exist here in the first place.
@oll3 Did you run it on windows?
Yes, a windows 10 pro machine, same as where I discovered the error in the first place.
Also tested the original snippet (the multiple runtimes etc) to ensure that it was ok. And it seems to be working with tokio master but still pacnicking on 0.2.22. So I think it's all good.