Session is now properly cleaned up
This commit is contained in:
parent
a5abe97735
commit
d5ddf4d294
3 changed files with 21 additions and 10 deletions
|
|
@ -642,7 +642,7 @@ impl Session {
|
||||||
if opts.enable_upnp_port_forwarding {
|
if opts.enable_upnp_port_forwarding {
|
||||||
session.spawn(
|
session.spawn(
|
||||||
error_span!(parent: session.rs(), "upnp_forward", port = listen_port),
|
error_span!(parent: session.rs(), "upnp_forward", port = listen_port),
|
||||||
session.clone().task_upnp_port_forwarder(listen_port),
|
Self::task_upnp_port_forwarder(listen_port),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -691,7 +691,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn check_incoming_connection(
|
async fn check_incoming_connection(
|
||||||
&self,
|
self: Arc<Self>,
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
mut stream: TcpStream,
|
mut stream: TcpStream,
|
||||||
) -> anyhow::Result<(Arc<TorrentStateLive>, CheckedIncomingConnection)> {
|
) -> anyhow::Result<(Arc<TorrentStateLive>, CheckedIncomingConnection)> {
|
||||||
|
|
@ -744,6 +744,8 @@ impl Session {
|
||||||
|
|
||||||
async fn task_tcp_listener(self: Arc<Self>, l: TcpListener) -> anyhow::Result<()> {
|
async fn task_tcp_listener(self: Arc<Self>, l: TcpListener) -> anyhow::Result<()> {
|
||||||
let mut futs = FuturesUnordered::new();
|
let mut futs = FuturesUnordered::new();
|
||||||
|
let session = Arc::downgrade(&self);
|
||||||
|
drop(self);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
|
@ -751,13 +753,15 @@ impl Session {
|
||||||
match r {
|
match r {
|
||||||
Ok((stream, addr)) => {
|
Ok((stream, addr)) => {
|
||||||
trace!("accepted connection from {addr}");
|
trace!("accepted connection from {addr}");
|
||||||
|
let session = session.upgrade().context("session is dead")?;
|
||||||
|
let span = error_span!(parent: session.rs(), "incoming", addr=%addr);
|
||||||
futs.push(
|
futs.push(
|
||||||
self.check_incoming_connection(addr, stream)
|
session.check_incoming_connection(addr, stream)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
debug!("error checking incoming connection: {e:#}");
|
debug!("error checking incoming connection: {e:#}");
|
||||||
e
|
e
|
||||||
})
|
})
|
||||||
.instrument(error_span!(parent: self.rs(), "incoming", addr=%addr))
|
.instrument(span)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -775,7 +779,7 @@ impl Session {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn task_upnp_port_forwarder(self: Arc<Self>, port: u16) -> anyhow::Result<()> {
|
async fn task_upnp_port_forwarder(port: u16) -> anyhow::Result<()> {
|
||||||
let pf = librqbit_upnp::UpnpPortForwarder::new(vec![port], None)?;
|
let pf = librqbit_upnp::UpnpPortForwarder::new(vec![port], None)?;
|
||||||
pf.run_forever().await
|
pf.run_forever().await
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use atomic::AtomicSessionStats;
|
use atomic::AtomicSessionStats;
|
||||||
use librqbit_core::speed_estimator::SpeedEstimator;
|
use librqbit_core::speed_estimator::SpeedEstimator;
|
||||||
use snapshot::SessionStatsSnapshot;
|
use snapshot::SessionStatsSnapshot;
|
||||||
|
|
@ -40,12 +41,13 @@ impl Default for SessionStats {
|
||||||
impl Session {
|
impl Session {
|
||||||
pub(crate) fn start_speed_estimator_updater(self: &Arc<Self>) {
|
pub(crate) fn start_speed_estimator_updater(self: &Arc<Self>) {
|
||||||
self.spawn(error_span!(parent: self.rs(), "speed_estimator"), {
|
self.spawn(error_span!(parent: self.rs(), "speed_estimator"), {
|
||||||
let s = self.clone();
|
let s = Arc::downgrade(self);
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
let mut i = tokio::time::interval(Duration::from_secs(1));
|
let mut i = tokio::time::interval(Duration::from_secs(1));
|
||||||
loop {
|
loop {
|
||||||
i.tick().await;
|
i.tick().await;
|
||||||
|
let s = s.upgrade().context("session is dead")?;
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let fetched = s.stats.atomic.fetched_bytes.load(Ordering::Relaxed);
|
let fetched = s.stats.atomic.fetched_bytes.load(Ordering::Relaxed);
|
||||||
let uploaded = s.stats.atomic.uploaded_bytes.load(Ordering::Relaxed);
|
let uploaded = s.stats.atomic.uploaded_bytes.load(Ordering::Relaxed);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ async fn test_e2e_download() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Wait to ensure everything is dropped.
|
// Wait to ensure everything is dropped.
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||||
|
|
||||||
let metrics = tokio::runtime::Handle::current().metrics();
|
let metrics = tokio::runtime::Handle::current().metrics();
|
||||||
assert_eq!(metrics.num_alive_tasks(), 1);
|
assert_eq!(metrics.num_alive_tasks(), 1);
|
||||||
|
|
@ -157,12 +157,13 @@ async fn _test_e2e_download(drop_checks: &DropChecks) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("torrent is live");
|
info!("torrent is live");
|
||||||
Ok::<_, anyhow::Error>(SocketAddr::new(
|
let addr = SocketAddr::new(
|
||||||
std::net::IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
std::net::IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||||
session
|
session
|
||||||
.tcp_listen_port()
|
.tcp_listen_port()
|
||||||
.context("expected session.tcp_listen_port() to be set")?,
|
.context("expected session.tcp_listen_port() to be set")?,
|
||||||
))
|
);
|
||||||
|
Ok::<_, anyhow::Error>((session, addr))
|
||||||
}
|
}
|
||||||
.instrument(error_span!("server", id = i)),
|
.instrument(error_span!("server", id = i)),
|
||||||
);
|
);
|
||||||
|
|
@ -170,12 +171,15 @@ async fn _test_e2e_download(drop_checks: &DropChecks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut peers = Vec::new();
|
let mut peers = Vec::new();
|
||||||
|
|
||||||
|
// This is around just not to drop.
|
||||||
|
let mut _servers = Vec::new();
|
||||||
for (id, peer) in futures::future::join_all(futs)
|
for (id, peer) in futures::future::join_all(futs)
|
||||||
.await
|
.await
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let peer = peer
|
let (server, peer) = peer
|
||||||
.with_context(|| format!("join error, server={id}"))
|
.with_context(|| format!("join error, server={id}"))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_context(|| format!("timeout, server={id}"))
|
.with_context(|| format!("timeout, server={id}"))
|
||||||
|
|
@ -183,6 +187,7 @@ async fn _test_e2e_download(drop_checks: &DropChecks) {
|
||||||
.with_context(|| format!("server couldn't start, server={id}"))
|
.with_context(|| format!("server couldn't start, server={id}"))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
peers.push(peer);
|
peers.push(peer);
|
||||||
|
_servers.push(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("started all servers, starting client");
|
info!("started all servers, starting client");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue