Skip to content

Commit

Permalink
[EH] Make abort() work with Wasm EH (#16910)
Browse files Browse the repository at this point in the history
We used to implement `abort()` with throwing a JS exception. #9730
changed it to `RuntimeError`, because it is the class a trap becomes
once it hits a JS frame.

But this turned out to be not working, because Wasm EH currently does
not assume all `RuntimeError`s are from traps; it decides whether a
`RuntimeError` is from a trap or not based on a hidden field within the
object. Relevant past discussion:
WebAssembly/exception-handling#89 (comment)

So at the moment we don't have a way of throwing a trap from JS, which
is inconvenient. I think we eventually want to make JS API for this, but
for the moment, this PR resorts to a wasm function that traps. This at
least makes calling `std::terminate` work. So far calling it exhausted
the call stack and aborted.
  • Loading branch information
aheejin authored May 11, 2022
1 parent 64034cf commit 4cf36b6
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
3 changes: 3 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2570,6 +2570,9 @@ def get_full_import_name(name):
if settings.SUPPORT_LONGJMP == 'wasm':
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('__c_longjmp')

if settings.EXCEPTION_HANDLING:
settings.REQUIRED_EXPORTS += ['__trap']

return target, wasm_target


Expand Down
11 changes: 10 additions & 1 deletion src/preamble.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,12 +605,20 @@ function abort(what) {
// Use a wasm runtime error, because a JS error might be seen as a foreign
// exception, which means we'd run destructors on it. We need the error to
// simply make the program stop.
// FIXME This approach does not work in Wasm EH because it currently does not assume
// all RuntimeErrors are from traps; it decides whether a RuntimeError is from
// a trap or not based on a hidden field within the object. So at the moment
// we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
// allows this in the wasm spec.

// Suppress closure compiler warning here. Closure compiler's builtin extern
// defintion for WebAssembly.RuntimeError claims it takes no arguments even
// though it can.
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.

#if EXCEPTION_HANDLING == 1
// See above, in the meantime, we resort to wasm code for trapping.
___trap();
#else
/** @suppress {checkTypes} */
var e = new WebAssembly.RuntimeError(what);

Expand All @@ -621,6 +629,7 @@ function abort(what) {
// in code paths apart from instantiation where an exception is expected
// to be thrown when abort is called.
throw e;
#endif
}

// {{MEM_INITIALIZER}}
Expand Down
3 changes: 3 additions & 0 deletions system/lib/compiler-rt/__trap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void __trap() {
__builtin_trap();
}
18 changes: 18 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1655,6 +1655,24 @@ class Polymorphic {virtual void member(){}};
}
''', 'exception caught: std::bad_typeid')

@with_both_eh_sjlj
def test_abort_no_dtors(self):
# abort() should not run destructors
out = self.do_run(r'''
#include <stdlib.h>
#include <iostream>
struct Foo {
~Foo() { std::cout << "Destructing Foo" << std::endl; }
};
int main() {
Foo f;
abort();
}
''', assert_returncode=NON_ZERO)
self.assertNotContained('Destructing Foo', out)

def test_iostream_ctors(self):
# iostream stuff must be globally constructed before user global
# constructors, so iostream works in global constructors
Expand Down
3 changes: 2 additions & 1 deletion tools/system_libs.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,8 @@ class libcompiler_rt(MTLibrary, SjLjLibrary):
'stack_ops.S',
'stack_limits.S',
'emscripten_setjmp.c',
'emscripten_exception_builtins.c'
'emscripten_exception_builtins.c',
'__trap.c',
])


Expand Down

0 comments on commit 4cf36b6

Please sign in to comment.