• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::ptr::null;
2 use futures_core::task::{RawWaker, RawWakerVTable, Waker};
3 
clone_panic_waker(_data: *const ()) -> RawWaker4 unsafe fn clone_panic_waker(_data: *const ()) -> RawWaker {
5     raw_panic_waker()
6 }
7 
noop(_data: *const ())8 unsafe fn noop(_data: *const ()) {}
9 
wake_panic(_data: *const ())10 unsafe 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() -> RawWaker19 const 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() -> Waker35 pub 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 Waker52 pub 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