Properly killing native apps from the host side
Context
I've been working on ocre-runtime, a project that runs WebAssembly (WASM) applications using wasm-micro-runtime. Ocre supports both Zephyr and Linux, and its core functionality involves creating, running, stopping, and restarting multiple WASM apps—including those designed to run indefinitely (e.g., blinky, echo-server).
The Issue
After introducing networking, we noticed that resources aren't being cleaned up properly—even though we're calling the recommended cleanup functions from the C/C++ Embed Guide.
What's Different
Unlike the guide, we spawn a separate thread for each WASM app. When we destroy an app, we terminate its thread and invoke the cleanup routines. However, this approach doesn't fully release resources. If the app exits cleanly on its own, everything works fine. But if we kill the thread externally, cleanup fails—even when calling the appropriate functions.
Repro Steps
I've created a minimal demo repo: kr-t/embedding-wasm-simple
/sample_appcontains the.wasmbinarymain.cin the root runs the app twice- Use
build.shto compile first the WASM app, then the C app for Linux
Expected output:
**********************************************
Server is starting...
Server listening on port 8000
**********************************************
Server is starting...
Server listening on port 8000
bind: Address in use
The second run fails because the socket wasn't released properly.
What We've Tried
- Creating a separate execution environment from host to native with a custom "shutdown" function that calls
close(socket)andexit(0)— same result as killing the thread externally - Using
fork()instead of threads works on Linux, but similar function isn't available not on Zephyr. Still, it demonstrates the behavior we want
Question
Is there a way to terminate WASM applications from the host side while ensuring all resources are properly cleaned up—so that restarting the same app doesn't cause unexpected behavior?
If not, is there a recommended workaround? We'd prefer not to require app developers to avoid blocking calls or implement custom signal handling, if possible.
Thanks for your time! Let me know if you need more details or have ideas for a solution.
wamr is not cancellation safe. use wasm_runtime_terminate to terminate the instance instead.
Hi @yamt , I have tested the suggested solution both on Linux and Zephyr:
- On Linux it works fine - after terminating the instance via API above, it seems to be cleaning up the garbage and the next time I try binding to the same port - it binds and works.
- On Zephyr it seems that it doesn't work the same way - I see no difference, and my address is still in use after the termination.
Do you have any suggestion, maybe config parameter of what I shall be doing differently on Zephyr compared to Linux, in order to achieve the same result? Thanks in advance!
the underlying api (os_wakeup_blocking_op etc) is not implemented for all platforms. zephyr doesn't seem to have it.
Thanks, I've checked the code, I see it now. I believe I got all my answers; if you think this functionality might be useful and we shall keep this issue open for somebody to implement it correctly, we can keep it. Otherwise I'm fine closing it.
the tricky part is that it needs to somehow cancel host functions like WASI. for unix-like platforms it's implemented using signals as signals can interrupt most of blocking system calls there. as i'm not familiar with zephyr, i don't know what OS functionality there can be used for this purpose.