Skip to content

Commit c853b73

Browse files
committed
fix: drop reqwest Client and DNS Resolver in dedicated thread
When NetworkState is dropped inside a tokio runtime, the internal tokio runtimes of reqwest::blocking::Client and trust-dns Resolver panic with 'Cannot drop a runtime in a context where blocking is not allowed'. OffThreadDrop wrapper moves destruction to a dedicated OS thread.
1 parent 6ab8a3f commit c853b73

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

crates/wasm-runtime-interface/src/network.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,39 @@ impl HostFunctionRegistrar for NetworkHostFunctions {
156156
}
157157
}
158158

159+
/// Wrapper that drops the inner value in a dedicated OS thread.
160+
/// Both `reqwest::blocking::Client` and `trust_dns_resolver::Resolver`
161+
/// own an internal tokio runtime. Dropping them inside an async context
162+
/// panics with "Cannot drop a runtime in a context where blocking is not
163+
/// allowed". This wrapper moves the drop to a short-lived thread.
164+
struct OffThreadDrop<T: Send + 'static>(Option<T>);
165+
166+
impl<T: Send + 'static> OffThreadDrop<T> {
167+
fn new(val: T) -> Self {
168+
Self(Some(val))
169+
}
170+
}
171+
172+
impl<T: Send + 'static> std::ops::Deref for OffThreadDrop<T> {
173+
type Target = T;
174+
fn deref(&self) -> &T {
175+
self.0.as_ref().unwrap()
176+
}
177+
}
178+
179+
impl<T: Send + 'static> Drop for OffThreadDrop<T> {
180+
fn drop(&mut self) {
181+
if let Some(val) = self.0.take() {
182+
std::thread::spawn(move || drop(val));
183+
}
184+
}
185+
}
186+
159187
pub struct NetworkState {
160188
policy: ValidatedNetworkPolicy,
161189
audit_logger: Option<Arc<dyn NetworkAuditLogger>>,
162-
http_client: Client,
163-
dns_resolver: Arc<Resolver>,
190+
http_client: OffThreadDrop<Client>,
191+
dns_resolver: Arc<OffThreadDrop<Resolver>>,
164192
dns_cache: HashMap<DnsCacheKey, DnsCacheEntry>,
165193
requests_made: u32,
166194
dns_lookups: u32,
@@ -215,7 +243,10 @@ impl NetworkState {
215243
let resolver = Resolver::new(ResolverConfig::default(), resolver_opts)
216244
.map_err(|err| NetworkStateError::DnsResolver(err.to_string()))?;
217245

218-
Ok::<_, NetworkStateError>((client, Arc::new(resolver)))
246+
Ok::<_, NetworkStateError>((
247+
OffThreadDrop::new(client),
248+
Arc::new(OffThreadDrop::new(resolver)),
249+
))
219250
})
220251
.join()
221252
.map_err(|_| {

0 commit comments

Comments
 (0)