Skip to content

[EH] Add option to make exception arg accessing easier #17114

@aheejin

Description

@aheejin

#17064 made it possible to access thrown values in Wasm EH and print messages, but it is still hard to use because the user needs to export several functions manually, which is illustrated in the test code in test_exception_message:

emscripten/tests/test_core.py

Lines 1636 to 1713 in 2a3bb65

@no_wasm64('MEMORY64 does not yet support exceptions')
@with_both_eh_sjlj
def test_exception_message(self):
self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$getExceptionMessage', '$incrementExceptionRefcount', '$decrementExceptionRefcount'])
self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'getExceptionMessage', '___get_exception_message'])
if '-fwasm-exceptions' in self.emcc_args:
exports = self.get_setting('EXPORTED_FUNCTIONS')
self.set_setting('EXPORTED_FUNCTIONS', exports + ['___cpp_exception', '___increment_wasm_exception_refcount', '___decrement_wasm_exception_refcount'])
# FIXME Temporary workaround. See 'FIXME' in the test source code below for
# details.
if self.get_setting('DISABLE_EXCEPTION_CATCHING') == 0:
self.emcc_args.append('-D__USING_EMSCRIPTEN_EXCEPTION__')
self.maybe_closure()
src = '''
#include <emscripten.h>
#include <exception>
#include <stdexcept>
using namespace std;
class myexception : public exception {
virtual const char* what() const throw() { return "My exception happened"; }
} myex;
EMSCRIPTEN_KEEPALIVE extern "C" void throw_exc(int x) {
if (x == 1) {
throw 1000;
}
if (x == 2) {
throw 'c';
}
if (x == 3) {
throw runtime_error("abc");
}
if (x == 4) {
throw myex;
}
if (x == 5) {
throw "abc";
}
}
int main() {
EM_ASM({
for (let i = 1; i < 6; i++){
try {
_throw_exc(i);
} catch(p) {
// Because we are catching and handling the exception in JS, the normal
// exception catching C++ code doesn't kick in, so we need to make sure we free
// the exception, if necessary. By incrementing and decrementing the refcount
// we trigger the free'ing of the exception if its refcount was zero.
#ifdef __USING_EMSCRIPTEN_EXCEPTION__
// FIXME Currently Wasm EH and Emscripten EH increases
// refcounts in different places. Wasm EH sets the refcount to
// 1 when throwing, and decrease it in __cxa_end_catch.
// Emscripten EH sets the refcount to 0 when throwing, and
// increase it in __cxa_begin_catch, and decrease it in
// __cxa_end_catch. Fix this inconsistency later.
incrementExceptionRefcount(p);
#endif
console.log(getExceptionMessage(p));
decrementExceptionRefcount(p);
}
}
});
}
'''
expected = '''\
exception of type int
exception of type char
exception of type std::runtime_error: abc
exception of type myexception: My exception happened
exception of type char const*
'''
self.do_run(src, expected)

It'd be good to make this easier to use by creating a single option that adds all necessary imports and exports the tag.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions