1 use core::ptr::null; 2 use futures_core::task::{RawWaker, RawWakerVTable, Waker}; 3 clone_panic_waker(_data: *const ()) -> RawWaker4unsafe fn clone_panic_waker(_data: *const ()) -> RawWaker { 5 raw_panic_waker() 6 } 7 noop(_data: *const ())8unsafe fn noop(_data: *const ()) {} 9 wake_panic(_data: *const ())10unsafe fn wake_panic(_data: *const ()) { 11 if !std::thread::panicking() { 12 panic!("should not be woken"); 13 } 14 } 15 16 const PANIC_WAKER_VTABLE: RawWakerVTable = 17 RawWakerVTable::new(clone_panic_waker, wake_panic, wake_panic, noop); 18 raw_panic_waker() -> RawWaker19const fn raw_panic_waker() -> RawWaker { 20 RawWaker::new(null(), &PANIC_WAKER_VTABLE) 21 } 22 23 /// Create a new [`Waker`](futures_core::task::Waker) which will 24 /// panic when `wake()` is called on it. The [`Waker`] can be converted 25 /// into a [`Waker`] which will behave the same way. 26 /// 27 /// # Examples 28 /// 29 /// ```should_panic 30 /// use futures_test::task::panic_waker; 31 /// 32 /// let waker = panic_waker(); 33 /// waker.wake(); // Will panic 34 /// ``` panic_waker() -> Waker35pub fn panic_waker() -> Waker { 36 // FIXME: Since 1.46.0 we can use transmute in consts, allowing this function to be const. 37 unsafe { Waker::from_raw(raw_panic_waker()) } 38 } 39 40 /// Get a global reference to a 41 /// [`Waker`](futures_core::task::Waker) referencing a singleton 42 /// instance of a [`Waker`] which panics when woken. 43 /// 44 /// # Examples 45 /// 46 /// ```should_panic 47 /// use futures_test::task::panic_waker_ref; 48 /// 49 /// let waker = panic_waker_ref(); 50 /// waker.wake_by_ref(); // Will panic 51 /// ``` panic_waker_ref() -> &'static Waker52pub fn panic_waker_ref() -> &'static Waker { 53 struct SyncRawWaker(RawWaker); 54 unsafe impl Sync for SyncRawWaker {} 55 56 static PANIC_WAKER_INSTANCE: SyncRawWaker = SyncRawWaker(raw_panic_waker()); 57 58 // SAFETY: `Waker` is #[repr(transparent)] over its `RawWaker`. 59 unsafe { &*(&PANIC_WAKER_INSTANCE.0 as *const RawWaker as *const Waker) } 60 } 61 62 #[cfg(test)] 63 mod tests { 64 #[test] 65 #[should_panic(expected = "should not be woken")] issue_2091_cross_thread_segfault()66 fn issue_2091_cross_thread_segfault() { 67 let waker = std::thread::spawn(super::panic_waker_ref).join().unwrap(); 68 waker.wake_by_ref(); 69 } 70 } 71