From: LukeMathWalker <20745048+LukeMathWalker@users.noreply.github.com> Date: Thu, 16 May 2024 08:59:59 +0000 (+0200) Subject: Explain how tokio::spawn behaves with respect to panics. X-Git-Url: http://git.euphorik.ch/?a=commitdiff_plain;h=73e7ddf91377e0df7fd7107efa7a3d7e998a864f;p=rust_exercises.git Explain how tokio::spawn behaves with respect to panics. --- diff --git a/book/src/08_futures/02_spawn.md b/book/src/08_futures/02_spawn.md index e6a1171..2dbae0a 100644 --- a/book/src/08_futures/02_spawn.md +++ b/book/src/08_futures/02_spawn.md @@ -79,7 +79,35 @@ pub async fn emit_telemetry() { pub async fn do_work() { // [...] } +``` + +### Panic boundary + +If a task spawned with `tokio::spawn` panics, the panic will be caught by the executor. +If you don't `.await` the corresponding `JoinHandle`, the panic won't be propagated to the spawner. +Even if you do `.await` the `JoinHandle`, the panic won't be propagated automatically. +Awaiting a `JoinHandle` returns a `Result`, with [`JoinError`](https://docs.rs/tokio/latest/tokio/task/struct.JoinError.html) +as its error type. You can then check if the task panicked by calling `JoinError::is_panic` and +choose what to do with the panic—either log it, ignore it, or propagate it. +```rust +use tokio::task::JoinError; + +pub async fn run() { + let handle = tokio::spawn(work()); + if let Err(e) = handle.await { + if let Ok(reason) = e.try_into_panic() { + // The task has panicked + // We resume unwinding the panic, + // thus propagating it to the current thread + panic::resume_unwind(reason); + } + } +} + +pub async fn work() { + // [...] +} ``` ### `std::thread::spawn` vs `tokio::spawn`