Skip to content

Commit 14ea477

Browse files
committed
refactor(iroh-dns): let the conn-pool reaper self-terminate via Weak
The reaper now holds a Weak reference to the pool and exits once the pool is dropped, instead of holding the connections alive behind an AbortOnDropHandle. Dropping the pool (e.g. when a network change rebuilds the resolver) now closes its idle sockets immediately rather than waiting for the task abort to propagate, and there is no join handle to store.
1 parent ff77034 commit 14ea477

1 file changed

Lines changed: 15 additions & 12 deletions

File tree

iroh-dns/src/dns/resolver/pool.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@
1616
//! once and never again does not pin a socket open forever.
1717
//!
1818
//! The task is spawned lazily on the first check-in (always inside an async
19-
//! query, hence inside a runtime) and aborted when the pool is dropped.
19+
//! query, hence inside a runtime). It holds only a [`Weak`] reference, so it
20+
//! self-terminates once the pool is dropped (and dropping the pool closes its
21+
//! idle sockets right away rather than waiting on the task).
2022
2123
use std::{
2224
collections::HashMap,
2325
net::SocketAddr,
24-
sync::{Arc, Mutex, OnceLock},
26+
sync::{Arc, Mutex, OnceLock, Weak},
2527
};
2628

2729
use n0_future::{
28-
task::{AbortOnDropHandle, spawn},
30+
task::spawn,
2931
time::{self, Duration, Instant},
3032
};
3133
use tokio::net::TcpStream;
@@ -85,8 +87,8 @@ impl Inner {
8587
/// A pool of idle TCP and DoT connections, keyed by nameserver.
8688
pub(super) struct ConnPool {
8789
inner: Arc<Inner>,
88-
/// The idle-connection reaper, spawned on first check-in and aborted on drop.
89-
reaper: OnceLock<AbortOnDropHandle<()>>,
90+
/// Set once the idle-connection reaper has been spawned.
91+
reaper_spawned: OnceLock<()>,
9092
}
9193

9294
impl std::fmt::Debug for ConnPool {
@@ -99,7 +101,7 @@ impl ConnPool {
99101
pub(super) fn new() -> Self {
100102
Self {
101103
inner: Arc::new(Inner::default()),
102-
reaper: OnceLock::new(),
104+
reaper_spawned: OnceLock::new(),
103105
}
104106
}
105107

@@ -146,18 +148,19 @@ impl ConnPool {
146148
/// Spawns the reaper task on first use. Check-in always runs inside an async
147149
/// query, so a runtime is guaranteed to be present.
148150
fn ensure_reaper(&self) {
149-
self.reaper.get_or_init(|| {
150-
let inner = Arc::clone(&self.inner);
151-
AbortOnDropHandle::new(spawn(reap_loop(inner)))
151+
self.reaper_spawned.get_or_init(|| {
152+
spawn(reap_loop(Arc::downgrade(&self.inner)));
152153
});
153154
}
154155
}
155156

156-
/// Periodically drops idle connections until the pool is dropped (which aborts
157-
/// this task via its [`AbortOnDropHandle`]).
158-
async fn reap_loop(inner: Arc<Inner>) {
157+
/// Periodically drops idle connections, exiting once the pool is gone.
158+
async fn reap_loop(inner: Weak<Inner>) {
159159
loop {
160160
time::sleep(REAP_INTERVAL).await;
161+
let Some(inner) = inner.upgrade() else {
162+
return;
163+
};
161164
inner.reap();
162165
}
163166
}

0 commit comments

Comments
 (0)