Skip to content

Commit b73df64

Browse files
committed
fix: wrap both reqwest::blocking::Client and DNS resolver creation in dedicated thread
Both reqwest::blocking::Client::build() and trust-dns Resolver::new() internally call block_on which panics inside a tokio runtime.
1 parent 9d63a53 commit b73df64

File tree

2 files changed

+37
-30
lines changed

2 files changed

+37
-30
lines changed

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

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -184,38 +184,44 @@ impl NetworkState {
184184
Policy::limited(validated.limits.max_redirects as usize)
185185
};
186186

187-
let http_client = Client::builder()
188-
.timeout(Duration::from_millis(validated.limits.timeout_ms))
189-
.redirect(redirect_policy)
190-
.build()
191-
.map_err(|err| NetworkStateError::HttpClient(err.to_string()))?;
192-
193-
let mut resolver_opts = ResolverOpts::default();
194-
resolver_opts.timeout = Duration::from_millis(validated.limits.timeout_ms);
195-
resolver_opts.attempts = 1;
196-
resolver_opts.cache_size = 0;
197-
resolver_opts.use_hosts_file = false;
198-
resolver_opts.num_concurrent_reqs = 1;
199-
200-
if validated.dns_policy.cache_ttl_secs > 0 {
201-
let ttl = Duration::from_secs(validated.dns_policy.cache_ttl_secs);
202-
resolver_opts.positive_min_ttl = Some(ttl);
203-
resolver_opts.positive_max_ttl = Some(ttl);
204-
resolver_opts.negative_min_ttl = Some(ttl);
205-
resolver_opts.negative_max_ttl = Some(ttl);
206-
}
187+
// Create HTTP client and DNS resolver in a dedicated thread to avoid
188+
// "Cannot start a runtime from within a runtime" panic. Both
189+
// reqwest::blocking::Client and trust-dns Resolver internally call
190+
// block_on, which panics inside an existing tokio runtime.
191+
let timeout_ms = validated.limits.timeout_ms;
192+
let dns_cache_ttl = validated.dns_policy.cache_ttl_secs;
193+
let (http_client, dns_resolver) = std::thread::spawn(move || {
194+
let client = Client::builder()
195+
.timeout(Duration::from_millis(timeout_ms))
196+
.redirect(redirect_policy)
197+
.build()
198+
.map_err(|err| NetworkStateError::HttpClient(err.to_string()))?;
199+
200+
let mut resolver_opts = ResolverOpts::default();
201+
resolver_opts.timeout = Duration::from_millis(timeout_ms);
202+
resolver_opts.attempts = 1;
203+
resolver_opts.cache_size = 0;
204+
resolver_opts.use_hosts_file = false;
205+
resolver_opts.num_concurrent_reqs = 1;
206+
207+
if dns_cache_ttl > 0 {
208+
let ttl = Duration::from_secs(dns_cache_ttl);
209+
resolver_opts.positive_min_ttl = Some(ttl);
210+
resolver_opts.positive_max_ttl = Some(ttl);
211+
resolver_opts.negative_min_ttl = Some(ttl);
212+
resolver_opts.negative_max_ttl = Some(ttl);
213+
}
207214

208-
// Create DNS resolver in a dedicated thread to avoid
209-
// "Cannot start a runtime from within a runtime" panic when
210-
// trust-dns internally calls block_on during initialization.
211-
let dns_resolver =
212-
std::thread::spawn(move || Resolver::new(ResolverConfig::default(), resolver_opts))
213-
.join()
214-
.map_err(|_| {
215-
NetworkStateError::DnsResolver("DNS resolver thread panicked".to_string())
216-
})?
215+
let resolver = Resolver::new(ResolverConfig::default(), resolver_opts)
217216
.map_err(|err| NetworkStateError::DnsResolver(err.to_string()))?;
218217

218+
Ok::<_, NetworkStateError>((client, resolver))
219+
})
220+
.join()
221+
.map_err(|_| {
222+
NetworkStateError::HttpClient("HTTP/DNS init thread panicked".to_string())
223+
})??;
224+
219225
Ok(Self {
220226
policy: validated,
221227
audit_logger,

docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ services:
6363

6464
volumes:
6565
validator-data:
66-
driver: local
66+
external: true
67+
name: platform_validator-data

0 commit comments

Comments
 (0)