aisuneko
aisuneko

Reputation: 21

How to pass &OsStr paths between threads using a channel?

I'm writing a Rust program that spawns an array of threads, each given the path of a directory. Each thread iterates through the said path with the walkdir crate and sends the nested paths through a channel:

use std::ffi::OsStr;
use std::path::Path;
use std::thread;
use std::sync::mpsc;

use walkdir::WalkDir;

fn func(tx: mpsc::Sender<&OsStr>, path: &Path) {
    for entry in WalkDir::new(&path) {
        if let Ok(entry) = entry {
            tx.send(entry.file_name()).unwrap();
        }
    }
}

fn main() {
    let dir_list: Vec<String> = ...;
    let (tx, rx) = mpsc::channel();

    let handles: Vec<_> = dir_list
        .into_iter()
        .map(|dir_path| {
            let txc = tx.clone();
            thread::spawn(move || func(txc, Path::new(&dir_path)))
        })
        .collect();

    for h in handles {
        let _ = h.join();
    }

    ...
}

The compiler complains about lifetime issues with entry.file_name(). Seems that the error means it should live throughout the entire function, which is not possible due to the use of a for loop for different directory paths:

error[E0597]: `entry` does not live long enough
  --> src/main.rs:11:21
   |
8  | fn func(tx: mpsc::Sender<&OsStr>, path: &Path) {
   |                          - let's call the lifetime of this reference `'1`
9  |     for entry in WalkDir::new(&path) {
10 |         if let Ok(entry) = entry {
   |                   ----- binding `entry` declared here
11 |             tx.send(entry.file_name()).unwrap();
   |             --------^^^^^-------------
   |             |       |
   |             |       borrowed value does not live long enough
   |             argument requires that `entry` is borrowed for `'1`
12 |         }
   |         - `entry` dropped here while still borrowed

What should I do? If it's impossible to solve due to being an ownership problem with messages and threads, what other alternatives should I try? I need to pass entry.file_name() to the channel upon each iteration.

Upvotes: -1

Views: 84

Answers (1)

aisuneko
aisuneko

Reputation: 21

Solved by appending .to_os_string() to entry.file_name(); that is, promote it from &OsStr to OsString. Turns out that you should send owned types instead of borrowed references in channels, for Sender's lifetime depends on the type (?).

Upvotes: 1

Related Questions