Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion emcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,7 @@ def phase_linker_setup(options, state, newargs, user_settings):
# TODO: Move this into the library JS file once it becomes possible.
# See https://github.com/emscripten-core/emscripten/pull/15982
if settings.INCLUDE_FULL_LIBRARY and not settings.DISABLE_EXCEPTION_CATCHING:
settings.EXPORTED_FUNCTIONS += ['_emscripten_format_exception', '_free']
settings.EXPORTED_FUNCTIONS += ['___get_exception_message', '_free']

if settings.WASM_WORKERS:
# TODO: After #15982 is resolved, these dependencies can be declared in library_wasm_worker.js
Expand Down
6 changes: 3 additions & 3 deletions src/library_exceptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,9 @@ var LibraryExceptions = {
},

#if !DISABLE_EXCEPTION_CATCHING
$formatException__deps: ['emscripten_format_exception', 'free'],
$formatException: function(excPtr) {
var utf8_addr = _emscripten_format_exception(excPtr);
$getExceptionMessage__deps: ['__get_exception_message', 'free'],
$getExceptionMessage: function(excPtr) {
var utf8_addr = ___get_exception_message(excPtr);
var result = UTF8ToString(utf8_addr);
_free(utf8_addr);
return result;
Expand Down
16 changes: 12 additions & 4 deletions system/lib/libcxxabi/src/cxa_exception_emscripten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cxa_exception_from_thrown_object(void* thrown_object) {

extern "C" {

char* emscripten_format_exception(void* thrown_object) {
char* __get_exception_message(void* thrown_object, bool terminate=false) {
__cxa_exception* exception_header =
cxa_exception_from_thrown_object(thrown_object);
const __shim_type_info* thrown_type =
Expand All @@ -45,19 +45,27 @@ char* emscripten_format_exception(void* thrown_object) {
const char* what =
static_cast<const std::exception*>(thrown_object)->what();
asprintf(&result,
"terminating with uncaught exception of type %s: %s",
(terminate ? "terminating with uncaught exception of type %s: %s"
: "exception of type %s: %s"),
type_name,
what);
} else {
asprintf(
&result, "terminating with uncaught exception of type %s", type_name);
asprintf(&result,
(terminate ? "terminating with uncaught exception of type %s"
: "exception of type %s"),
type_name);
}

if (demangled_buf) {
free(demangled_buf);
}
return result;
}

char* __get_exception_terminate_message(void *thrown_object) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we don't have any current caller of this yet, but we will do soon (perhaps in debug builds, or some opt-in configuration)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I'd like to use it later, and this PR doesn't have a direct test for this, but I think holding this small piece off is probably not worth it..

return __get_exception_message(thrown_object, true);
}

}

#endif // __USING_EMSCRIPTEN_EXCEPTIONS__
20 changes: 10 additions & 10 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1608,10 +1608,10 @@ def test_exceptions_rethrow_missing(self):
self.do_runf('main.cpp', None, assert_returncode=NON_ZERO)

@no_wasm64('MEMORY64 does not yet support exceptions')
def test_format_exception(self):
def test_exception_message(self):
self.set_setting('DISABLE_EXCEPTION_CATCHING', 0)
self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$formatException', '__cxa_decrement_exception_refcount', '__cxa_increment_exception_refcount'])
self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'formatException', '_emscripten_format_exception', '_free'])
self.set_setting('DEFAULT_LIBRARY_FUNCS_TO_INCLUDE', ['$getExceptionMessage', '__cxa_decrement_exception_refcount', '__cxa_increment_exception_refcount'])
self.set_setting('EXPORTED_FUNCTIONS', ['_main', 'getExceptionMessage', '___get_exception_message', '_free'])
self.maybe_closure()
src = '''
#include <emscripten.h>
Expand Down Expand Up @@ -1645,26 +1645,26 @@ class myexception : public exception {
EM_ASM({
for (let i = 1; i < 6; i++){
try {
Module["_throw_exc"](i);
_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.
___cxa_increment_exception_refcount(p);
console.log(Module["formatException"](p).replace(/0x[0-9a-f]*/, "xxx"));
Copy link
Member Author

@aheejin aheejin May 25, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hoodmane By the way I have a question. Is there a reason we can't call this just like

console.log(formatException(p));

?

The same for Module["_throw_exc"] in line 1648.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure, try it and see?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From outside the module you would need Module["formatException"].. but for JS that is inside the module (e.g. EM_ASM and EM_JS code) then you can just do formatException.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Changed them to direct calls.

console.log(getExceptionMessage(p));
___cxa_decrement_exception_refcount(p);
}
}
});
}
'''
expected = '''\
terminating with uncaught exception of type int
terminating with uncaught exception of type char
terminating with uncaught exception of type std::runtime_error: abc
terminating with uncaught exception of type myexception: My exception happened
terminating with uncaught exception of type char const*
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)
Expand Down