Reqwest::get() gives DNS error with tokio::spawn()

The following code is a modified version of the example code to demonstrate the above problem:

use std::collections::HashMap;

#[tokio::main]
async fn main() {
    for i in 1..5 {
        let i = i;
        tokio::spawn(async move {
            match doit(i).await {
                Err(e) => println!("error: {}", e),
                _ => {}
            };
        });
    }
}

async fn doit(i: usize) -> Result<(), Box<dyn std::error::Error>> {
    println!("{} time", i);
    let resp = reqwest::get("https://httpbin.org/ip")
        .await?
        .json::<HashMap<String, String>>()
        .await?;
    println!("{:#?}", resp);
    Ok(())
}

On running this with cargo run, the following errors are returned:

1 time
error: error sending request for url (https://httpbin.org/ip): error trying to connect: dns error: cancelled
2 time
error: error sending request for url (https://httpbin.org/ip): error trying to connect: dns error: cancelled
3 time
error: error sending request for url (https://httpbin.org/ip): error trying to connect: dns error: cancelled
4 time
error: error sending request for url (https://httpbin.org/ip): error trying to connect: dns error: cancelled

I am running this on Arch Linux (Linux 5.9.14-arch1-1).

Why is this error caused and/or how do I get around it?

There is no guarantee that a spawned task will execute to completion. When a runtime is shutdown, all outstanding tasks are dropped, regardless of the lifecycle of that task.

What this means is that you need to make sure that your main function doesn’t return until the tasks are completed. The easiest way to do this would be to push the JoinHandles to a Vec, then await them in a second loop.