Propagating errors from within a closure in a thread in Rust

Viewed 4033

I want to propagate an error from a function called inside a closure inside a call to thread::spawn.

I've tried using a JoinHandle to capture the result of thread::spawn, but I get various errors doing that.

fn start_server(args) -> Result<(), Box<dyn std::error::Error>> {
    ...
    thread::spawn(move || {
        // I want to do this (put a ? after run_server)
        run_server(args)?;
        ...
    }
    ...        
});
fn run_server(args) -> Result<(), std::io::Error> {
    ...
}

I get this message

|             run_server(args)?;
|             ^^^^^^^^^^^^^^^^^ cannot use the `?` operator in a function that returns `()`
|
= help: the trait `std::ops::Try` is not implemented for `()`
= note: required by `std::ops::Try::from_error`
1 Answers

I want to propagate an error from a function called inside a closure inside a call to thread::spawn

Since threads are running in parallel, throwing the error up from the thread scope is not making sense. Better approach will be error handling in the thread itself.

So generally you should not propagate the error to the upper level above the thread.

However you can throw your error that you get in your parallel threads after you joined them to your main thread. This way it will be pretty much like error propagation in synchronous.

Here is how you can manage it:

fn start_server() -> Result<(), Box<std::error::Error>> {
    let x = std::thread::spawn(move || -> Result<(), std::io::Error> {
        run_server()?;
        Ok(())
    });

    x.join().unwrap()?; // Now you can throw your error up because you joined your thread.
                        // ...
    Ok(())
}

fn run_server() -> Result<(), std::io::Error> {
    Err(std::io::Error::new(std::io::ErrorKind::Other, "hello"))
}

fn main() {
    let x = start_server();
    println!("{:?}", x);
}

Playground

Related