bytecodealliance / bytecodealliance/wasmtime
New API doesn't let you access memory while async function call is in progress
- Dominant language
- Rust
- Stars
- 18.6k
- Forks
- 1.8k
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 126
Description
:wave:
I have an existing code that is using `wasmtime 0.27`, and that is doing more or less something like this (pseudo-code):
```rust
let my_func = instance.get_export("foo").unwrap().into_func().unwrap();
let my_memory = instance.get_export("memory").unwrap().into_memory().unwrap();
let future = my_func.call_async(&[]);
futures::pin_mut!(future);
loop {
// Execute a bit of Wasm.
(&mut future).now_or_never();
// Read the memory of the Wasm VM.
let data = my_memory.read(...);
if some_cond(&data) {
break;
}
}
```
The actual code is a bit more complicated than that (I'm also sharing a struct between the host functions and the caller), but I'm basically using `call_async` in order to start execution, manually polling the future returned by `call_async`, and while the execution is paused I can read/write the memory of the Wasm VM.
I've been trying to upgrade to `wasmtime 0.28`, but [the new API](https://github.com/bytecodealliance/rfcs/pull/11) is giving me a lot of trouble.
Calling `call_async` now requires passing an `impl AsMutContext` that is being held for the entire duration of the call, meaning that we lose the ability to read/write memory from outside the host functions while the asynchronous call is in progress.
I was wondering if you could give me suggestions on how to upgrade :pray:
## What I've tried
My little snippet maybe implies that the Wasm memory is used as a vector of communication between the host functions and the "outside", and that this could be refactored. But in practice the fact that I can read/write the memory of the Wasm function while execution is paused is something deeply ingrained in the API of my code (as this seems like a sensible thing to do), and tens of thousands of lines of code depend on the ability to do that.
I've been trying to think of a way to pass to `call_async` some sort of glorified `Arc>` that would implement `AsMutContext`, but I believe that the way the trait is defined makes it impossible to do in a safe way.
There is a way to implement this safely:
The `Caller<_>` that is accessible by the host functions can be used to read and write memory, so in principle one could imagine a system where an `Rc>>` is shared between the "outside" and the host functions, where `Operation` is some sort of `enum { ReadMemory(_), WriteMemory(_) }` and host functions process these operations after each `await`.
However this seems like a lot of complication.
One potential change in `wasmtime` that could make sense to me would be to implement `AsContext` and `AsContextMut` on the future returned by `call_async`. In practice, however, this seems almost impossible to implement.
Thanks in advance!
Contributor guide
Assessment
This issue has not been assessed yet.