Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async exported func cancel safety? #10088

Open
SupernaviX opened this issue Jan 23, 2025 · 1 comment
Open

Async exported func cancel safety? #10088

SupernaviX opened this issue Jan 23, 2025 · 1 comment

Comments

@SupernaviX
Copy link

Hello!

I'm contributing to a project which calls async wasmtime exports. Sometimes, those exported functions start failing with the error "wasm trap: cannot enter component instance". I think the issue might be that the generated wasm client isn't cancel-safe.

Here's the relevant snippet from the generated code (generated by wit-bindgen 0.38):

            let _enter = span.enter();
            let callee = unsafe {
                wasmtime::component::TypedFunc::<(u32, &Event,),(Result<Response,HandleError>,)>::new_unchecked(self.handle)
            };
            let(ret0,) = callee.call_async(store.as_context_mut(),(arg0,arg1,)).await?;
            callee.post_return_async(store.as_context_mut()).await?;
            Ok(ret0)

The docs say that if you call TypedFunc's call_async method, you must call post_return_async. If this snippet is cancelled during that call to call_async. then it looks like post_return_async will never be called (and there doesn't seem to be a way to recover from that).

Am I right that this code isn't cancel-safe? And if so, is there any way to recover from the cancellation?

@alexcrichton
Copy link
Member

Thanks for the report! Even setting aside components it's pretty unlikely that any core wasm module is cancel-safe in terms of dropping a call_async future. Destructors are not run with wasm on the stack meaning that any state in the wasm module is leaked including the stack pointer itself. Given that what the component model is doing here is codifying what you probably want anyway which is to throw away the component entirely whenever an async call is cancelled. Otherwise you have no way of knowing robustly what was on the wasm stack and what was cancelled on the wasm side.

That's a bit of a winded way of saying that this is expected behavior. It's not intended to be recoverable once you drop a call_async future. The "cancel safe" part is that you're deterministically prevented from reentering the wasm module. Currently there's no way to opt-in to "yes ok but I really know the wasm is cancel-safe" and if that's what you're looking for here I think it'd be ok to add that to the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants