Skip to content

Commit

Permalink
[EH] Make abort() work with EH
Browse files Browse the repository at this point in the history
We used to implement `abort()` with throwing a JS exception. emscripten-core#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.

Fixes emscripten-core#16407.
  • Loading branch information
aheejin committed May 6, 2022
1 parent f650912 commit 97b7bcc
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 2 deletions.
3 changes: 3 additions & 0 deletions emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2566,6 +2566,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 is not working now, because Wasm EH 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 trap from JS. TODO Make a JS API that
// allows this.
// 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
// 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
6 changes: 6 additions & 0 deletions system/lib/compiler-rt/exception_builtins.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.globl __trap

__trap:
.functype __trap() -> ()
unreachable
end_function
14 changes: 14 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,20 @@ class Polymorphic {virtual void member(){}};
}
''', 'exception caught: std::bad_typeid')

@with_both_eh_sjlj
def test_terminate_abort(self):
# std::terminate eventually calls abort(). We used ti implement abort() with
# throwing a JS exception, but this can be again caught by std::terminate's
# cleanup and cause an infinite loop. When Wasm EH is enabled, abort() is
# implemented by a trap now.
err = self.do_run(r'''
#include <exception>
int main() {
std::terminate();
}
''', assert_returncode=NON_ZERO)
self.assertNotContained('Maximum call stack size exceeded', err)

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',
'exception_builtins.S'
])


Expand Down

0 comments on commit 97b7bcc

Please sign in to comment.