proxy-wasm / proxy-wasm-cpp-sdk

WebAssembly for Proxies (C++ SDK)
Apache License 2.0
139 stars 67 forks source link

Support for exceptions .. Disabling emscripten-cxx-exceptions #140

Open jlb6740 opened 2 years ago

jlb6740 commented 2 years ago

Hi .. Enabling exceptions for WASM seems to conflict with an -fno-exceptions flag being used by emscripten during linking. For example, if I add a try and catch in the example and build with:

bazel build //example:http_wasm_example.wasm --features=exceptions

The build fails with the following error:

jlbirch@jlbirch:~/proxy-wasm-cpp-sdk-jlb6740/example$ bazel build //example:http_wasm_example.wasm --features=exceptions --verbose_failures INFO: Analyzed target //example:http_wasm_example.wasm (0 packages loaded, 0 targets configured). INFO: Found 1 target... ERROR: /home/jlbirch/proxy-wasm-cpp-sdk-jlb6740/example/BUILD:5:21: Linking example/proxy_wasm_http_wasm_example failed: (Exit 1): emcc_link.sh failed: error executing command (cd /home/jlbirch/.cache/bazel/_bazel_jlbirch/7341316095ecd002ea18765f811f48f4/sandbox/linux-sandbox/26/execroot/proxy_wasm_cpp_sdk && \ exec env - \ EMCC_WASM_BACKEND=1 \ EM_BIN_PATH=external/emscripten_bin_linux \ EM_CONFIG_PATH=external/emsdk/emscripten_toolchain/emscripten_config \ PATH=/home/jlbirch/.cache/bazelisk/downloads/bazelbuild/bazel-4.1.0-linux-x86_64/bin:/home/jlbirch/.wasmer/bin:/home/jlbirch/emsdk:/home/jlbirch/emsdk/upstream/emscripten:/home/jlbirch/emsdk/node/14.18.2_64bit/bin:/opt/intel/oneapi/vtune/2022.2.0/bin64:/opt/intel/oneapi/vtune/latest/bin64:/opt/intel/oneapi/vtune/latest/android_target:/home/jlbirch/.wasmtime/bin:/home/jlbirch/.vscode-server/bin/6cba118ac49a1b88332f312a8f67186f7f3c1643/bin:/home/jlbirch/.local/bin:/home/jlbirch/.wasmer/bin:/home/jlbirch/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/jlbirch/sde-external-9.0.0-2021-11-07-lin/:/home/jlbirch/wabt/build/:/home/jlbirch/node-v16.16.0-linux-x64/bin/:/home/jlbirch/.wasmer/globals/wapm_packages/.bin:/home/jlbirch/.wasmer/globals/wapm_packages/.bin \ PWD=/proc/self/cwd \ external/emsdk/emscripten_toolchain/emcc_link.sh @bazel-out/wasm-fastbuild-ST-7840e1c24980/bin/example/proxy_wasm_http_wasm_example-2.params) Execution platform: @local_config_platform//:host

Use --sandbox_debug to see verbose messages from the sandbox error: DISABLE_EXCEPTION_THROWING was set (likely due to -fno-exceptions), which means no C++ exception throwing support code is linked in, but exception catching code appears. Either do not set DISABLE_EXCEPTION_THROWING (if you do want exception throwing) or compile all source files with -fno-except (so that no exceptions support code is required); also make sure DISABLE_EXCEPTION_CATCHING is set to the right value - if you want exceptions, it should be off, and vice versa. error: DISABLE_EXCEPTION_THROWING was set (likely due to -fno-exceptions), which means no C++ exception throwing support code is linked in, but exception catching code appears. Either do not set DISABLE_EXCEPTION_THROWING (if you do want exception throwing) or compile all source files with -fno-except (so that no exceptions support code is required); also make sure DISABLE_EXCEPTION_CATCHING is set to the right value - if you want exceptions, it should be off, and vice versa. error: undefined symbol: resumeException (referenced by top-level compiled C/C++ code) warning: Link with -s LLD_REPORT_UNDEFINED to get more information on undefined symbols warning: To disable errors for undefined symbols use -s ERROR_ON_UNDEFINED_SYMBOLS=0 warning: _resumeException may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library Error: Aborting compilation due to previous errors emcc: error: '/home/jlbirch/.cache/bazel/_bazel_jlbirch/7341316095ecd002ea18765f811f48f4/sandbox/linux-sandbox/26/execroot/proxy_wasm_cpp_sdk/external/nodejs_linux_amd64/bin/node /home/jlbirch/.cache/bazel/_bazel_jlbirch/7341316095ecd002ea18765f811f48f4/external/emscripten_bin_linux/emscripten/src/compiler.js /tmp/tmpr68z5zhw.json' failed (returned 1) Target //example:http_wasm_example.wasm failed to build INFO: Elapsed time: 2.611s, Critical Path: 2.47s INFO: 5 processes: 2 internal, 3 linux-sandbox. FAILED: Build did NOT complete successfully

The line in building.py of a very recent version of emscripten that emits the -fno-exceptions looks like this:

if not settings.DISABLE_EXCEPTION_CATCHING: args += ['-enable-emscripten-cxx-exceptions']

Is there a way to programmatically set the setting of DISABLE_EXCEPTION_CATCHING in bazel build files? Currently I am forced to comment out the lines here.

PiotrSikora commented 2 years ago

Looking at the errors, it looks that --features=exceptions actually works and enables exceptions.

The issue is that ___resumeException and other hostcalls are not available during build, so you need to either disable this check (--linkopt=-sERROR_ON_UNDEFINED_SYMBOLS=0 should work) or create a JavaScript stub with prototypes for those functions (similarly to how Emscripten is made aware of Proxy-Wasm hostcalls using proxy_wasm_intrinsics.js).

However, even if you get plugins to compile, Proxy-Wasm C++ Host / Envoy / Istio don't support C++ exceptions, so this all might be futile.

jlb6740 commented 2 years ago

Hi @PiotrSikora .. Thanks for the response. So I've updated the BUILD file for the example like this:

proxy_wasm_cc_binary( name = "http_wasm_example.wasm", srcs = ["http_wasm_example.cc"], copts = ["-std=c++17", "-fwasm-exceptions"], linkopts = ["-fwasm-exceptions -sERROR_ON_UNDEFINED_SYMBOLS=0"], )

But am still getting the same error? But beyond that we are definitely trying to run a filter that requires exception handling and its disconcerting to hear it won't work in Envoy/Istio. (1) What work is needed to get that support in (and how much/difficult is that work)? (2) Are there workarounds to implement in Envoy/Istio for handling exceptions that wouldn't require modification to the filter?

PiotrSikora commented 2 years ago

I think you need to add a comma between linkopts.

Regarding support for C++ exceptions in Envoy/Istio, there is a bug tracking it here: https://github.com/proxy-wasm/proxy-wasm-cpp-host/issues/116.

To be honest, I didn't look at it since the support for native Wasm exceptions was added to V8 and Wasmtime. Perhaps it "just works"? But it looks that Emscripten still uses some JavaScript wrappers for them. Maybe @sbc100 can tell us more?

jlb6740 commented 2 years ago

Thanks. Yes, exception support seems to work now in V8 as of I think version v9.5 (the latest envoy is using v10.4) and in emscripten as of 3.1.16. I've tried in node and chrome devtools in the browser and both now show the same behavior as compiling C++ to native for the example tried. Perhaps it will work .. we just need to try?

About the flag, I tried both ways and tried via the command line but it makes no noticeable impact.

proxy_wasm_cc_binary( name = "http_wasm_example.wasm", srcs = ["http_wasm_example.cc"], copts = ["-std=c++17", "-fwasm-exceptions"], linkopts = ["-fwasm-exceptions", "-sERROR_ON_UNDEFINED_SYMBOLS=0"], )

PiotrSikora commented 2 years ago

Are you sure that we need both -fexceptions (enabled by --features=exceptions) and -fwasm-exceptions?

jlb6740 commented 2 years ago

Yeah, the flag combination is just not at clear to me and obviously will be dependent and become even less clear when considering the version of emscripten matters. I'm using very close to the latest release. It seems the fwasm-exceptions is needed. If I remove that then there is an undefined symbol:

wasm-ld: error: bazel-out/wasm-fastbuild-ST-6632493ac585/bin/example/_objs/proxy_wasm_http_wasm_example/http_wasm_example.o: undefined symbol: __wasm_lpad_context

which in quick reading appears to related to the landing location for exception handling. If I remove the -fexceptions on the bazel command I get:

cannot use 'throw' with exceptions disabled

Seems both are needed. I'm wondering if this confusion is managable with bazel build flags or if there is something with emscripten that needs to be filed. I'm hoping to figure this out with the right combination of build flags.