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).