-
Notifications
You must be signed in to change notification settings - Fork 16
Open
Description
If a Rust future is co_awaited from C++ and that future decides to wake the current task, then a deadlock will occur.
Found while trying to use futures::FuturesUnordered which wakes the current task here.
I attach a minimal example below.
main.hh:
#pragma once
#include "rust/cxx.h"
#include "cxx-async/include/rust/cxx_async.h"
CXXASYNC_DEFINE_FUTURE(void, RustFutureVoid);
RustFutureVoid run_cpp();main.cc:
#include "main.hh"
#include "cxx-async-self-wake-bug/src/main.rs.h"
RustFutureVoid run_cpp() {
co_await run_rust();
}main.rs:
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use crate::ffi::run_cpp;
#[cxx::bridge]
mod ffi {
extern "Rust" {
fn run_rust() -> RustFutureVoid;
}
unsafe extern "C++" {
include!("main.hh");
fn run_cpp() -> RustFutureVoid;
type RustFutureVoid = crate::RustFutureVoid;
}
}
#[cxx_async::bridge]
unsafe impl Future for RustFutureVoid {
type Output = ();
}
pub fn run_rust() -> RustFutureVoid {
RustFutureVoid::infallible(YieldFuture { yielded: false })
}
struct YieldFuture {
yielded: bool,
}
impl Future for YieldFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
if !self.yielded {
// Yield, but also wake immediately
self.as_mut().yielded = true;
cx.waker().wake_by_ref();
Poll::Pending
} else {
Poll::Ready(())
}
}
}
fn main() {
println!("Start!");
futures::executor::block_on(run_cpp()).unwrap();
println!("Finish!");
}Only "Start!" is printed, then the program deadlocks.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels