-
Notifications
You must be signed in to change notification settings - Fork 9
Closed
bytecodealliance/wit-bindgen
#1197Description
Not sure if this is a in issue in wit-bindgen
, wasmtime
or both, but it appears that the Waker
functionality does not function correctly in Rust guests when using async exports.
For example:
use futures::channel::mpsc;
use futures::join;
use futures::{SinkExt as _, StreamExt as _};
struct Component;
wasi::cli::command::export!(Component);
impl wasi::exports::cli::run::Guest for Component {
async fn run() -> Result<(), ()> {
let (mut tx, mut rx) = mpsc::channel(1);
join!(
async {
_ = rx.next().await;
},
async {
_ = tx.send(()).await;
}
);
Ok(())
}
}
with Cargo.toml
:
[package]
name = "p3-test"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
futures = "0.3"
wasi = { git = "https://github.com/rvolosatovs/wasi", branch = "feat/p3" }
wasi
repo is pointing to commit rvolosatovs/wasi@0792066
executed via:
cargo build --release --target wasm32-unknown-unknown && ~/.cargo/bin/wasm-tools component new --skip-validation target/wasm32-unknown-unknown/release/p3_test.wasm -o component.wasm && ~/src/github.com/bytecodealliance/wasmtime/target/debug/wasmtime run component.wasm
Produces:
Error: failed to run main module `component.wasm`
Caused by:
wasm trap: async-lifted export failed to produce a result
That's using Wasmtime from #60
Interestingly, causing a task allocation from the guest turns the error into a deadlock (which is how I first encountered the issue and is the reason for the title), for example:
use futures::channel::mpsc;
use futures::join;
use futures::{SinkExt as _, StreamExt as _};
use wasi::wit_stream;
struct Component;
wasi::cli::command::export!(Component);
impl wasi::exports::cli::run::Guest for Component {
async fn run() -> Result<(), ()> {
let (mut tx, mut rx) = mpsc::channel(1);
let (_, stdout_rx) = wit_stream::new();
wasi::cli::stdout::set_stdout(stdout_rx);
join!(
async {
_ = rx.next().await;
},
async {
_ = tx.send(()).await;
}
);
Ok(())
}
}
Generally, it appears that there are 2 things happening here:
- when the component's "futures unordered" set is empty, the component is unable to await
async
functions not provided by the runtime - when the component's "futures unordered" set is non-empty, calling
Waker::wake
in the guest does not awake the task and so the component ends up in a deadlock state
Metadata
Metadata
Assignees
Labels
No labels