From fa117dee27fc162ad956d796aa7d706afda4964c Mon Sep 17 00:00:00 2001 From: John Nunley Date: Tue, 21 Nov 2023 02:39:09 -0800 Subject: [PATCH] Propagate panics in tasks (#78) After smol-rs/async-task#37 I meant to add this to the executor. This commit makes it so all panics are surfaced in the tasks that the user calls. Hopefully this improves ergonomics. Signed-off-by: John Nunley Signed-off-by: Alain Zscheile --- src/lib.rs | 14 +++++++++++--- tests/panic_prop.rs | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/panic_prop.rs diff --git a/src/lib.rs b/src/lib.rs index dcc1f99..7116794 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ use std::sync::{Arc, Mutex, RwLock, TryLockError}; use std::task::{Poll, Waker}; use async_lock::OnceCell; -use async_task::Runnable; +use async_task::{Builder, Runnable}; use concurrent_queue::ConcurrentQueue; use futures_lite::{future, prelude::*}; use slab::Slab; @@ -159,7 +159,11 @@ impl<'a> Executor<'a> { }; // Create the task and register it in the set of active tasks. - let (runnable, task) = unsafe { async_task::spawn_unchecked(future, self.schedule()) }; + let (runnable, task) = unsafe { + Builder::new() + .propagate_panic(true) + .spawn_unchecked(|()| future, self.schedule()) + }; active.insert(runnable.waker()); runnable.schedule(); @@ -402,7 +406,11 @@ impl<'a> LocalExecutor<'a> { }; // Create the task and register it in the set of active tasks. - let (runnable, task) = unsafe { async_task::spawn_unchecked(future, self.schedule()) }; + let (runnable, task) = unsafe { + Builder::new() + .propagate_panic(true) + .spawn_unchecked(|()| future, self.schedule()) + }; active.insert(runnable.waker()); runnable.schedule(); diff --git a/tests/panic_prop.rs b/tests/panic_prop.rs new file mode 100644 index 0000000..eab4901 --- /dev/null +++ b/tests/panic_prop.rs @@ -0,0 +1,14 @@ +use async_executor::Executor; +use futures_lite::{future, prelude::*}; + +#[test] +fn test_panic_propagation() { + let ex = Executor::new(); + let task = ex.spawn(async { panic!("should be caught by the task") }); + + // Running the executor should not panic. + assert!(ex.try_tick()); + + // Polling the task should. + assert!(future::block_on(task.catch_unwind()).is_err()); +}