diff options
Diffstat (limited to 'src/sync/tests/notify.rs')
-rw-r--r-- | src/sync/tests/notify.rs | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/src/sync/tests/notify.rs b/src/sync/tests/notify.rs index eb0da8f..323b5c6 100644 --- a/src/sync/tests/notify.rs +++ b/src/sync/tests/notify.rs @@ -1,10 +1,9 @@ use crate::sync::Notify; use std::future::Future; -use std::mem::ManuallyDrop; use std::sync::Arc; use std::task::{Context, RawWaker, RawWakerVTable, Waker}; -#[cfg(tokio_wasm_not_wasi)] +#[cfg(all(target_family = "wasm", not(target_os = "wasi")))] use wasm_bindgen_test::wasm_bindgen_test as test; #[test] @@ -12,16 +11,16 @@ fn notify_clones_waker_before_lock() { const VTABLE: &RawWakerVTable = &RawWakerVTable::new(clone_w, wake, wake_by_ref, drop_w); unsafe fn clone_w(data: *const ()) -> RawWaker { - let arc = ManuallyDrop::new(Arc::<Notify>::from_raw(data as *const Notify)); + let ptr = data as *const Notify; + Arc::<Notify>::increment_strong_count(ptr); // Or some other arbitrary code that shouldn't be executed while the // Notify wait list is locked. - arc.notify_one(); - let _arc_clone: ManuallyDrop<_> = arc.clone(); + (*ptr).notify_one(); RawWaker::new(data, VTABLE) } unsafe fn drop_w(data: *const ()) { - let _ = Arc::<Notify>::from_raw(data as *const Notify); + drop(Arc::<Notify>::from_raw(data as *const Notify)); } unsafe fn wake(_data: *const ()) { @@ -46,6 +45,45 @@ fn notify_clones_waker_before_lock() { let _ = future.poll(&mut cx); } +#[cfg(panic = "unwind")] +#[test] +fn notify_waiters_handles_panicking_waker() { + use futures::task::ArcWake; + + let notify = Arc::new(Notify::new()); + + struct PanickingWaker(Arc<Notify>); + + impl ArcWake for PanickingWaker { + fn wake_by_ref(_arc_self: &Arc<Self>) { + panic!("waker panicked"); + } + } + + let bad_fut = notify.notified(); + pin!(bad_fut); + + let waker = futures::task::waker(Arc::new(PanickingWaker(notify.clone()))); + let mut cx = Context::from_waker(&waker); + let _ = bad_fut.poll(&mut cx); + + let mut futs = Vec::new(); + for _ in 0..32 { + let mut fut = tokio_test::task::spawn(notify.notified()); + assert!(fut.poll().is_pending()); + futs.push(fut); + } + + assert!(std::panic::catch_unwind(|| { + notify.notify_waiters(); + }) + .is_err()); + + for mut fut in futs { + assert!(fut.poll().is_ready()); + } +} + #[test] fn notify_simple() { let notify = Notify::new(); @@ -63,7 +101,7 @@ fn notify_simple() { } #[test] -#[cfg(not(tokio_wasm))] +#[cfg(not(target_family = "wasm"))] fn watch_test() { let rt = crate::runtime::Builder::new_current_thread() .build() |