Stream: git-wasmtime

Topic: wasmtime / issue #11870 Functions defined with `wrap_asyn...


view this post on Zulip Wasmtime GitHub notifications bot (Oct 15 2025 at 21:50):

alexcrichton opened issue #11870:

This issue is similar to #11869 but I've separated it out to specifically deal with usage of block_on with respect to wrap_async and its variants. The wrap_async function has been a pillar of Wasmtime's async support historically but it's effectively entirely incompatible with component-model-async semantics. Notably wrap_async "locks" a store across await points meaning that it's not possible to progress other tasks at the same time. While this sort of means that wrap_async is "just another blocking call" from the perspective of a component it has the notable consequence of making run_concurrent not actually properly run things concurrently. Effectively this suffers from the same problems as #11869.

Fixing this issue is expected to be difficult. Ideally we'd "just delete all calls and use wrap_concurrent instead", but that's a pretty large change to make. That also doesn't clearly translate to core wasm where there's no equivalent of concurrent calls at this time. A more localized fix would be to remove all of Wasmtime's usage of wrap_async, document the pitfalls, and then move on. For example wasmtime-wasi would avoid using wrap_async and would use wrap_concurrent (or an equivalent thereof) instead. This wouldn't actually fix WASIp1 APIs since there's no *_concurrent available, though.

Regardless I wanted to write down this issue to have a place to discuss this and notably link to in the source/documentation about how this is a major limitation of run_concurrent today.

view this post on Zulip Wasmtime GitHub notifications bot (Oct 15 2025 at 21:50):

alexcrichton added the wasm-proposal:component-model-async label to Issue #11870.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 02 2026 at 05:41):

alexcrichton commented on issue #11870:

In talking with Joel/Luke some time ago, I wanted to write down thoughts relevant to this specifically as well. Notably the conclusion is that if wasm calls a synchronously-typed host function then it's not valid for the wasm to be reentered. This is entirely different for an async-typed host function but for synchronously-typed functions it's not valid for wasm to execute while the host is running.

This puts host calls in a similar situation as #11869 where when synchronous host functions are called we can't just start using run_concurrent. Instead there needs to be some sort of infrastructure to prevent executing more wasm, probably like the async lock described in https://github.com/bytecodealliance/wasmtime/issues/11869#issuecomment-3832992306.

This also showcases a glimmer of hope of being able to retain the function signature of func_wrap_async (sort of). Assuming the function signature there is changed to restrict to &mut T instead of StoreContextMut<T>, then that's sort of what happens under the hood. The host function gets to use &mut T and the execution of the host function will block the guest. All further guest invocations will also be blocked, too. This is almost the same as Rust's borrowing rules, but the problem that remains is the fact that "on the other end", the hypothetical run_concurrent block, the embedder still has a Accessor<T> which can temporarily grant StoreContextMut<T>. This gives unfettered access to T, even when it's being borrowed by a host function.

This is not safe in Rust, so something needs to be done. Some ideas, none of which I like, are:

I personally don't want to force all embedders to switch to run_concurrent just yet, but this may just be inevitable. That correctly and accurately models the ownership situations, which is that fundamentally you only get access to T temporarily, not for the duration of an async operation. It does sort of seem inevitable that func_wrap_async needs to become more restrictive one way or another. One end of the spectrum is deleting it outright, and the other end of the spectrum is having some sort of more restrictive trait bound which models some sort of common pattern of ownership.

Anyway, that's the thoughts for now at least.


Last updated: Feb 24 2026 at 06:21 UTC