futures-rs icon indicating copy to clipboard operation
futures-rs copied to clipboard

Different `waker_vtable` addresses for same type

Open afeistel opened this issue 1 year ago • 4 comments

use futures::task::ArcWake;

struct Temp;

impl ArcWake for Temp {
    fn wake_by_ref(arc_self: &std::sync::Arc<Self>) {
        let _ = arc_self;
    }
}

fn main() {
    let temp = std::sync::Arc::new(Temp);
    let waker = futures::task::waker_ref(&temp);
    println!("{waker:?} {:?}", waker.clone());
    futures::executor::block_on(async {});
}

Sometimes (more often than not, in my experience), when running in --release mode, vtable addresses don't match:

WakerRef { waker: ManuallyDrop { value: Waker { data: 0x5654d35e5b90, vtable: 0x5654d2ad62b8 } }, _marker: PhantomData<&()> } Waker { data: 0x5654d35e5b90, vtable: 0x5654d2ad6308 }

Why this matters: this leads to AtomicWaker and alike to clone (or, worse, wake) on each poll because of how Waker::will_wake compares Wakers. Example: https://github.com/sdroege/async-tungstenite/issues/133

Is this a compiler bug? If yes, can we do something to mitigate it?

afeistel avatar Jun 14 '24 18:06 afeistel

Same issue as https://github.com/rust-lang/futures-rs/pull/2829#issuecomment-1962863389 / https://github.com/rust-lang/rust/pull/121622#issuecomment-1975888092?

taiki-e avatar Jun 14 '24 19:06 taiki-e

yes, seems to be the same issue

afeistel avatar Jun 14 '24 19:06 afeistel

#[inline(always)] on clone_arc_raw has some positive effect on the situation sometimes (ref_wake_same passes?)

afeistel avatar Jun 14 '24 20:06 afeistel

Quoting myself from

[...] this sounds like a bug in the code doing the comparison. If multiple codegen units are involved, it's not guaranteed that the vtable is always the same for the same object.

That's why e.g. https://doc.rust-lang.org/stable/std/sync/struct.Arc.html#method.ptr_eq exists.

sdroege avatar Jun 15 '24 16:06 sdroege

Resolved by https://github.com/rust-lang/futures-rs/pull/2865

taiki-e avatar Oct 01 '24 14:10 taiki-e