Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tokio::JoinSet and hickory_resolver::Resolver causes "Cannot start a runtime from within a runtime" #2142

Open
ktravelet opened this issue Feb 9, 2024 · 2 comments

Comments

@ktravelet
Copy link

Rust newb here. I'm assuming I'm doing something wrong but I cant figure it out.

I created a minimal repro with the error below:

#[tokio::main]
async fn main() -> Result<(),()> {

    let max_async_threads = 1;
    let mut fqdns = Vec::<String>::new();

    while fqdns.len() < 2 {
        fqdns.push("google.com.".to_string());
    }

    let mut join_set = JoinSet::<(String)>::new();
    for fqdn in fqdns {
        
        while join_set.len() >= max_async_threads {
            let result = join_set.join_next().await.expect("Async to return").expect("DNS to resolve");
            println!("{}", result);
        }

        join_set.spawn(some_async(fqdn));
    }

    while let Some(result) = join_set.join_next().await {
        let address = result.expect("DNS to return");
        println!("{}", address);
    }
    
    Ok(())
}

async fn some_async(fqdn: String) -> String {
    let resolver: Resolver = Resolver::new(ResolverConfig::default(), ResolverOpts::default()).unwrap();
    let response: Ipv4Lookup = resolver.ipv4_lookup(fqdn).unwrap();
    let address = response.iter().next().expect("no addresses returned!");
    address.to_string()
}
thread 'thread 'tokio-runtime-workertokio-runtime-worker' panicked at ' panicked at C:\Users\kytravel\.cargo\registry\src\index.crates.io-6f17d22bba15001f\hickory-resolver-0.24.0\src\resolver.rsC:\Users\kytravel\.cargo\registry\src\index.crates.io-6f17d22bba15001f\hickory-resolver-0.24.0\src\resolver.rs::149149::55:
:
Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.
@bluejekyll
Copy link
Member

The docs should be a little clearer, and maybe we should disable this sync interface by default. You want to instead use the AsyncResolver: https://docs.rs/hickory-resolver/latest/hickory_resolver/struct.AsyncResolver.html#method.tokio

@ktravelet
Copy link
Author

that was the ticket! Thanks so much. Do you have a "buy me a coffee" link?

FYI for anyone coming across this. Correct code is here:

#[tokio::main]
async fn main() -> Result<(),()> {
    let max_async_threads = 10;
    let mut fqdns = Vec::<String>::new();

    while fqdns.len() < 100 {
        fqdns.push("google.com.".to_string());
    }

    let mut join_set = JoinSet::<(String)>::new();
    for fqdn in fqdns {
        
        while join_set.len() >= max_async_threads {
            let result = join_set.join_next().await.expect("Async to return").expect("DNS to resolve");
            println!("{}", result);
        }

        join_set.spawn(some_async(fqdn));
    }

    while let Some(result) = join_set.join_next().await {
        let address = result.expect("DNS to return");
        println!("{}", address);
    }
    
    Ok(())
}

async fn some_async(fqdn: String) -> String {
    let resolver = AsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default());
    let response: Ipv4Lookup = resolver.ipv4_lookup(fqdn).await.unwrap();
    let address = response.iter().next().expect("no addresses returned!");
    address.to_string()
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants