15

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`
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
fraiser
  • 929
  • 12
  • 28
  • When asking for why some code does not compile, you should include code that can be actually given to the compiler to show the error. Preferably with a link to a copy in https://play.rust-lang.org/. In this case the detail that hides the devil is in those `...` after `run_server(args)?`. That is, you didn't post enough details to answer why the closure returns `()`. – Jan Hudec Jun 11 '19 at 07:40

1 Answers1

12

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

Akiner Alkan
  • 6,145
  • 3
  • 32
  • 68