grmmgrmm
grmmgrmm

Reputation: 1408

How to extend lifetime for variable handed over to tokio spawned co-routine

I'm using tokio to create a new thread to execute a task on file paths found using walkdir. It basically looks like follows:

    pub async fn hash_tree(start_path: &Path) -> std::io::Result<()> {
        for entry in WalkDir::new(start_path) {
            let file_path_entry = entry.unwrap();
            let file_path = file_path_entry.path();
    
            let handle = tokio::spawn(async move {
                hashing::hash_file(file_path).await.unwrap();
            });
        }

The problem with this code is that the file path doesn't live long enough. Rust fails with:

error[E0597]: `file_path_entry` does not live long enough
  --> src/main.rs:44:25
   |
44 |         let file_path = file_path_entry.path();
   |                         ^^^^^^^^^^^^^^^^^^^^^^
   |                         |
   |                         borrowed value does not live long enough
   |                         argument requires that `file_path_entry` is borrowed for `'static`
...
61 |     }
   |     - `file_path_entry` dropped here while still borrowed

I understand the issue but I'm not sure how to tackle it. Would it be better to first gather all the file_paths in a vector and then push them into co-routines? I would rather prefer to kick the spawned task off as soon as it is found. Can I alternatively push copies of the file_paths to a vector that is owned by the outer scope so that I can make sure that they live long enough (EDIT: tried pushing the paths onto a vector with greater scope but that didn't work either)?

What would be alternative/better ways to handle that?

Upvotes: 0

Views: 831

Answers (1)

grmmgrmm
grmmgrmm

Reputation: 1408

Thanks Netwave and Masklinn! What finally worked was moving a clone of file_path_entry.clone(). As Masklinn pointed out, path is also borrowed. So, this works:

for entry in WalkDir::new(start_path).follow_links(false) {
    let file_path_entry = entry.unwrap();
    let handle = tokio::spawn(async move {
        hashing::hash_file(file_path_entry.clone()).await.unwrap();
    });

Upvotes: 1

Related Questions