bytedance/monoio

wake_by_ref() does not wake the executor

YjyJeff opened this issue · 1 comments

Version
0.0.9

Platform
OS: Ubuntu 20.4
Kernel version: 5.13.0

Description

I want to implement yield in tokio

I tried this code:

struct Yield {
    yielded: bool,
}

impl Future for Yield {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<()> {
        if self.yielded {
            Poll::Ready(())
        } else {
            self.yielded = true;
            ctx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

fn main(){
    let mut rt = RuntimeBuilder::<IoUringDriver>::new()
        .with_entries(1024)
        .build()
        .unwrap();
    rt.block_on(async move{
        let yield_now = Yield { yielded: false };
        yield_now.await;
    });
}

I expected to see this happen: runtime finishes the yield task

Instead, this happened: Code runs forever

AFAIK, according to the contract of the Waker, at least one poll should be called. BTW, I tested the code with tokio, it works fine

Update: If I enable the sync feature, the problem goes away. The problem happens in the block_on function of Runtime. If we do not enable the sync feature, the driver will go to park and tick the CQ. It seems that it ignores the dummy waker

Thanks for reporting!

I tried to fix it and it seems work.
The problem here was: We thought the main task must not be ready after a poll. But it can be, in this case, the main task is woken by itself.
If sync feature is enabled, the main task will be replaced by another generated one, and the user provided one is treated as a normal task, so it works fine.

The fix will be publish on the next release(within 3 days maybe).