Skip to content

Conversation

@aheejin
Copy link
Member

@aheejin aheejin commented Jan 7, 2026

getExceptionMessage didn't work with EXCEPTION_STACK_TRACES, which is also set when ASSERTIONS is set, in Emscripten EH. ASSERTIONSis the default mode for-O0`.

getExceptionMessage assumes the input ptr is a pointer, but when EXCEPTION_STACK_TRACES is set, it is an instance of CppException. in/decrementExceptionRefcount have the same problem. Now these methods check whether the pointer is a value or an instance of CppException.

In the test, self.set_setting('ASSERTIONS', 0) is removed. That way, we can test wit ASSERTIONS set in core0 and unset in core1+ settings.

Fixes #17115 (comment).

`getExceptionMessage` didn't work with `-sASSERTIONS`, which is the
default mode for `-O0`, because `getExceptionMessage` assumes the input
`ptr` is a pointer, whereas when `ASSERTIONS` is set, it is an instance
of `CppException`. `in/decrementExceptionRefcount` have the same
problem. Now these methods check whether the pointer is a value or an
instance of `CppException`.

Fixes
emscripten-core#17115 (comment).
Copy link
Collaborator

@kleisauke kleisauke left a comment

Choose a reason for hiding this comment

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

LGTM!


@with_all_eh_sjlj
def test_EXPORT_EXCEPTION_HANDLING_HELPERS(self):
self.set_setting('ASSERTIONS', 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Better to just remove this line. No need for the additional change below since core tests run in O0 mode with assertions enabled already.

Copy link
Member Author

@aheejin aheejin Jan 9, 2026

Choose a reason for hiding this comment

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

That may be sufficient for the testing of this PR, but then we don't get to test the case ASSERTIONS=0, when we don't use CppException wrapper, no?

In case it was not clear why we test both ASSERTIONS 0 and 1 at the bottom, I added some comments: 6115f33
Please let me know if you still think it's better to remove the loop.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But we already have the core0 and core1 configurations that test with ASSERTIONS=0 and ASSERTIONS=1. We shouldn't need to duplication that here, unless I'm missing something.

If there is a reason to test with ASSERTIONS=0 and ASSERTIONS=1 in all configurations then this should probably be @parameterized

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah right. Will remove it.

if (ptr instanceof CppException) {
ptr = ptr.excPtr;
}
#endif
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems a bit on that ptr might be something other than a pointer. Why not expect caller to always pass a pointer here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure if I understand. Do you mean, instead of doing the unwrapping here (and in getExceptionMessage and decrementExceptionRefcount), we should let the caller do the unwrapping? But the caller may be a user program:
https://github.com/emscripten-core/emscripten/blob/035c704d5cbeb85481eb1c3273617d21b881d674/test/test_core.py#L1553C19-L1553C45

And it can be confusing for the user to do different things depending on whether they are in ASSERTIONS mode or not.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But the user is already exposed to the difference aren't they? In one case they get a CppException object and in another case they get a pointer.

Is the idea that we are supposed to treat these two things the same a paper over the differences like this? It seems a little all. If we do want to do this consistently perhaps we should have some kind of helper/macro such as "caughtExceptionToPtr" or something like that?

Copy link
Member Author

@aheejin aheejin Jan 9, 2026

Choose a reason for hiding this comment

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

I think we can think of this as we providing overloaded convenience methods for similar but different types. Making the users change code depending on whether they build with -O0 and -On will be at best very inconvenient.

char const*,
'''

self.do_runf('main.cpp', expected)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you still need this line.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh thanks, restored it.

This previous commit deleted the test itself by mistake
#elif !DISABLE_EXCEPTION_CATCHING
$incrementExceptionRefcount__deps: ['__cxa_increment_exception_refcount'],
$incrementExceptionRefcount: (ptr) => ___cxa_increment_exception_refcount(ptr),
$incrementExceptionRefcount: (ptr) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you rename the incoming ptr param to something more meaningful?

And maybe add a little helper to get the ptr from an exception?

e.g.

$incrementExceptionRefcount: (exn) => {
  ___cxa_increment_exception_refcount(exnToPtr(exn));
},

Copy link
Member Author

Choose a reason for hiding this comment

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

Done: b574c4a
and typo fix 775e41d

@aheejin aheejin changed the title Make getExceptionMessage work with ASSERTIONS Make getExceptionMessage work with EXCEPTION_STACK_TRACES in Emscripten EH Jan 9, 2026
$getExceptionMessage__deps: ['$exnToPtr', '$getExceptionMessageCommon'],
$getExceptionMessage: (exn) => {
return getExceptionMessageCommon(exnToPtr(exn));
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

These can be reverted to single line functions now I think.

Otherwise lgtm!

Copy link
Member Author

Choose a reason for hiding this comment

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

Done: 73f045a

@aheejin aheejin merged commit 4c3a201 into emscripten-core:main Jan 10, 2026
35 checks passed
@aheejin aheejin deleted the fix_eh_getmessage_assertions branch January 10, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[EH] Fix inconsistency of refcounting in Emscripten EH vs. Wasm EH

3 participants