Exceptions thrown and caught within WebAssembly make Envoy drop the connection
When the code inside a wasm module throws an exception, and catches it within the same execution so that it does not cross the boundary between wasm and Envoy it drops the connection without a response.
I have created a reproducer for Istio Proxy 1.8.1 at https://github.com/robertpanzer/wasm-extensions The README explains how to test it.
Expected behavior: A wasm module should be able to throw and catch exceptions within Context::onRequestHeaders as long as onRequestHeaders does not return exceptionally.
Observed behavior: When a method throws an exception that is transitively called by onRequestHeaders, and the exception is caught by some other method in that call stack, Envoy drops the downstream connnection without providing any response.
How did you compile the module? Wasm instruction set does not support exceptions in principle (it does not have goto), so relooper must be applied to structure the control flow. Depending how complex non-local control flow transfer is, it can be pretty expensive.
On Wed, Dec 9, 2020 at 3:10 AM Robert Panzer [email protected] wrote:
When the code inside a wasm module throws an exception, and catches it within the same execution so that it does not cross the boundary between wasm and Envoy it drops the connection without a response.
I have created a reproducer for Istio Proxy 1.8.1 at https://github.com/robertpanzer/wasm-extensions The README explains how to test it.
Expected behavior: A wasm module should be able to throw and catch exceptions within Context::onRequestHeaders as long as onRequestHeaders does not return exceptionally.
Observed behavior: When a method throws an exception that is transitively called by onRequestHeaders, and the exception is caught by some other method in that call stack, Envoy drops the downstream connnection without providing any response.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/issues/80, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACIYRRQI3UPIDD7WLJ2Z7O3ST5LJBANCNFSM4UTKO4DQ .
Looks like code is compiled with O3 which disables all exception handling. See https://emscripten.org/docs/optimizing/Optimizing-Code.html#optimizing-code-exception-catching. DISABLE_EXCEPTION_CATCHING=0 can override but Emscripten recommends against exceptions to keep code small and fast.
On Wed, Dec 9, 2020 at 8:40 AM Kuat [email protected] wrote:
How did you compile the module? Wasm instruction set does not support exceptions in principle (it does not have goto), so relooper must be applied to structure the control flow. Depending how complex non-local control flow transfer is, it can be pretty expensive.
On Wed, Dec 9, 2020 at 3:10 AM Robert Panzer [email protected] wrote:
When the code inside a wasm module throws an exception, and catches it within the same execution so that it does not cross the boundary between wasm and Envoy it drops the connection without a response.
I have created a reproducer for Istio Proxy 1.8.1 at https://github.com/robertpanzer/wasm-extensions The README explains how to test it.
Expected behavior: A wasm module should be able to throw and catch exceptions within Context::onRequestHeaders as long as onRequestHeaders does not return exceptionally.
Observed behavior: When a method throws an exception that is transitively called by onRequestHeaders, and the exception is caught by some other method in that call stack, Envoy drops the downstream connnection without providing any response.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/proxy-wasm/proxy-wasm-cpp-sdk/issues/80, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACIYRRQI3UPIDD7WLJ2Z7O3ST5LJBANCNFSM4UTKO4DQ .
The project is simply generated from this document: https://github.com/istio-ecosystem/wasm-extensions/blob/master/doc/write-a-wasm-extension-with-cpp.md
I just read up a bit on relooper, I don't fully understand though how it would help with exception handling? It seems to process a CFG, that is it should work on a single function. So would that still work for a construct where exceptions are thrown between multiple larger building blocks, like from an AntLR parser to the plugin?
@kyessenov while this is true that exceptions should be avoided in new code targeting Wasm (or all code, depending on your preferences), sometimes you need to use existing C/C++ libraries that require them.
In any case, I've spent some time digging into this today, and I might have misrepresented the state of support for C++ exceptions a bit in our last meeting.
Emscripten supports C++ exceptions perfectly fine using -s DISABLE_EXCEPTION_CATCHING=0. We don't currently expose this in the SDK (cc @bianpengyuan), but you can add it to toolchain/emcc.sh in the C++ SDK and use --override_repository to test it for the time being.
However, using Wasm modules built this way requires non-trivial support from the host implementation (i.e. Envoy), which is completely missing right now. I filed an issue (https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/116) to add support for it, but I don't have any ETA right now.
I just read up a bit on relooper, I don't fully understand though how it would help with exception handling? It seems to process a CFG, that is it should work on a single function. So would that still work for a construct where exceptions are thrown between multiple larger building blocks, like from an AntLR parser to the plugin?
Emscripten uses Relooper under the hood (in fact, it's the main technical difficulty) for all non-local jumps (switch fallthrough, goto's). It should work for most code with exceptions. The main problem is it creates a lot more code and variables, which has a performance cost, some of it is gained back with compiler optimizations. But it's hard to say how much overhead it adds without measuring it. The perf overhead of exceptions is something that is hard to fix without Wasm changing itself.