@Chris Fallin @fitzgen (he/him) Regarding the OOM handling topic in today's meeting: I'm curious how you anticipate OOM errors will be handled. I imagine there are roughly three scenarios:
vec.try_push(foo)?I'm naively imagining #1 and #3 will be quite common and #2 will be rare. If that's true, then letting allocation failures panic, catching such panics at public API boundaries, and "poisoning" the store so it can't be used again could be a valid alternative approach. For the rare #2 cases, the same approach could be used at a finer-grained level: catch the panic, drop any half-formed state, and try the fallback code path.
I mentioned something like this last time it was brought up, but I don't recall if there were objections, and if so, what they were.
Yes mostly 1 and 3 but the problem with panics is that they internally allocate I am pretty sure and also they run destructors which if those attempt to allocate will lead to panic in panic which aborts
But also our nostd doesn’t support panic unwinding
Presumably propagating errors with ? will also run destructors.
but yeah, I see how it avoids the double panic
True but if allocations return a result then you shouldn’t just unwrap that in drop
yeah, either way you need to have well-behavedDrop implementations
I think what you describe is possible but feels a bit hackier / doesn’t match my sense of style as much. Having a hard time putting it into words
I guess I like that results don’t hide the error condition
If we are going to actually handle it, then we should be explicit about that
I'm not necessarily advocating for it: just feeling out the solution space, inspired a bit by Erlang-style supervision trees
If vec push doesn’t return a result, then why not use it in drop? But that’s a foot gun.
I do like the idea of poisoning stores and creating well defined boundaries
One other thing that throws the wrench into "catch the panic" is that we build with panic=abort right now because we don't have libunwind in our no-std environment. So this whole branch is out I think
in general I don't like DWARF being load-bearing here either
Yeah we would also have to unwind over wasm
indeed
There's also the aspect that I don't know we've tested/audited for correct disentangling of state via destructors at all possible failure points -- maybe? but there's a reason that e.g. mutexes get poisoned on panics, and there is cross-store state too (e.g. global module registry and the like)
We would sort of test that indirectly via the oom testing but yeah
Right, I guess I'm saying we need to eat the frog either way, so we might as well do it via "normal" control flow
While I agree that panicking in no_std is hard...
Yeah we would also have to unwind over wasm
this at least you don't have to deal with, we catch all panics in wasmtime at the wasm boundary, use a trap to unwind wasm, and then resume the panic on the other end
The unwinding crate can be used with no_std. Though you do need nightly to be able to set the personality function that libstd would otherwise set.
we talked about deserialization of cwasm's yesterday, and I just remembered that Postcard might be useful for that
Till Schneidereit said:
we talked about deserialization of cwasm's yesterday, and I just remembered that Postcard might be useful for that
we already use postcard today in fact: https://github.com/search?q=repo%3Abytecodealliance%2Fwasmtime%20postcard&type=code
but I have not figured out if it supports OOM-handling or not from a very quick glance at its docs. I do know that it reuses the serde traits, and I don't know if those interfaces are going to constrain us here
fitzgen (he/him) said:
but I have not figured out if it supports OOM-handling or not from a very quick glance at its docs. I do know that it reuses the serde traits, and I don't know if those interfaces are going to constrain us here
so I looked into this a little more and I think we can make it work if we create new collection types (eg wasmtime_collections::Vec) for our OOM-handling collections rather than do extension traits for std/alloc types.[^0] this is because we need a separate implementation of serde::Deserialize that does OOM handling, but there can only be one implementation of serde::Deserialize for one type.
[^0]: or alternatively use newtypes only within the things we want to deserialize with postcard/serde but if we are doing newtypes for this we might as well do it for all use sites
Last updated: Dec 06 2025 at 06:05 UTC