Skip to content

Commit 4cf36b6

Browse files
authored
[EH] Make abort() work with Wasm EH (#16910)
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.
1 parent 64034cf commit 4cf36b6

File tree

5 files changed

+36
-2
lines changed

5 files changed

+36
-2
lines changed

emcc.py

+3
Original file line numberDiff line numberDiff line change
@@ -2570,6 +2570,9 @@ def get_full_import_name(name):
25702570
if settings.SUPPORT_LONGJMP == 'wasm':
25712571
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('__c_longjmp')
25722572

2573+
if settings.EXCEPTION_HANDLING:
2574+
settings.REQUIRED_EXPORTS += ['__trap']
2575+
25732576
return target, wasm_target
25742577

25752578

src/preamble.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -605,12 +605,20 @@ function abort(what) {
605605
// Use a wasm runtime error, because a JS error might be seen as a foreign
606606
// exception, which means we'd run destructors on it. We need the error to
607607
// simply make the program stop.
608+
// FIXME This approach does not work in Wasm EH because it currently does not assume
609+
// all RuntimeErrors are from traps; it decides whether a RuntimeError is from
610+
// a trap or not based on a hidden field within the object. So at the moment
611+
// we don't have a way of throwing a wasm trap from JS. TODO Make a JS API that
612+
// allows this in the wasm spec.
608613

609614
// Suppress closure compiler warning here. Closure compiler's builtin extern
610615
// defintion for WebAssembly.RuntimeError claims it takes no arguments even
611616
// though it can.
612617
// TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
613-
618+
#if EXCEPTION_HANDLING == 1
619+
// See above, in the meantime, we resort to wasm code for trapping.
620+
___trap();
621+
#else
614622
/** @suppress {checkTypes} */
615623
var e = new WebAssembly.RuntimeError(what);
616624

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

626635
// {{MEM_INITIALIZER}}

system/lib/compiler-rt/__trap.c

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
void __trap() {
2+
__builtin_trap();
3+
}

tests/test_core.py

+18
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,24 @@ class Polymorphic {virtual void member(){}};
16551655
}
16561656
''', 'exception caught: std::bad_typeid')
16571657

1658+
@with_both_eh_sjlj
1659+
def test_abort_no_dtors(self):
1660+
# abort() should not run destructors
1661+
out = self.do_run(r'''
1662+
#include <stdlib.h>
1663+
#include <iostream>
1664+
1665+
struct Foo {
1666+
~Foo() { std::cout << "Destructing Foo" << std::endl; }
1667+
};
1668+
1669+
int main() {
1670+
Foo f;
1671+
abort();
1672+
}
1673+
''', assert_returncode=NON_ZERO)
1674+
self.assertNotContained('Destructing Foo', out)
1675+
16581676
def test_iostream_ctors(self):
16591677
# iostream stuff must be globally constructed before user global
16601678
# constructors, so iostream works in global constructors

tools/system_libs.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,8 @@ class libcompiler_rt(MTLibrary, SjLjLibrary):
708708
'stack_ops.S',
709709
'stack_limits.S',
710710
'emscripten_setjmp.c',
711-
'emscripten_exception_builtins.c'
711+
'emscripten_exception_builtins.c',
712+
'__trap.c',
712713
])
713714

714715

0 commit comments

Comments
 (0)