-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Propagate errors through val coroutine hierarchy. #23653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
I will add tests with separate commit... |
f703024
to
a966938
Compare
@RReverser added the coroutine part. I think he's been busy with other projects, but may have time. |
This PR looks reasonable, and I wanted this functionality myself in the past, but I wasn't (stil am not) sure if we should have coroutines / promises in Embind behave differently from synchronous function calls. Basically, I believe we should have a central flag that tells Embind "hey, store JS exceptions and make them catch-able from C++" regardless of whether function you're calling is synchronous, Asyncify one or a coroutine one - see #11496 for original issue. Having partial implementation where only one of those types of functions throws in C++ but not others might be surprising to users. |
I understand. I think I can propogate rejections through the promise hierarchy as well... The #11496 had been dragged for quite some time, without conclusion... About the improvement:
After adding similar await_transform in the val::promise it will be possible to write/integrate custom awaitables for custom user coroutines. For my case I will be able to seamlessly integrate in opposite direction and do
What do you think ? |
Do you actually see the leaks or do you only suspect it because there is no Explicit destroy is necessary only in some situations, like when using generators where you drive the coroutine rather it driving itself like happens with promises. I believe the way I implemented it back then was to ensure that coroutine destroys itself automatically, but if that doesn't actually work, please raise a separate issue demonstrating the problem. (I'll respond to the rest later, currently on the phone only) |
Sorry, my mistake: |
efbf14a
to
b5483e7
Compare
For what it's worth, this is already supported - I needed custom awaitables too in some places, so added that a while back - just by subclassing the awaiter instead. Here's the test showing an example and verifying it works: emscripten/test/embind/test_val_coro.cpp Lines 23 to 38 in 2e2ec08
Would this way of overloading work for your usecase? |
b5483e7
to
b8ed0cc
Compare
Lets move the discussion about that into a separate PR (or another platform), to not clutter this one. Getting back to the current PR. It is ready for review. |
As for the compiler errors, it seem something broke from an LLVM update and it appears to be fixed now. I've restarted the testers. |
b8ed0cc
to
a237f3a
Compare
a237f3a
to
cd558c6
Compare
OK, so it seems like that embind-rtti library is compiled without -pthread flag while the test itself (I am experimenting with the core0.test_pthread_create_embind_stack_check) is compiled with the -pthread flag and they are linked together... Is it OK to require libembind and libembind-rtti libraries to be compiled with the same threadness as the application and how do I do so for the tests ? EDIT: |
Seems like a reasonable solution yes. Its a pretty small library anyway. |
Fix bug when failure or exception happening in a >1 level of the val coroutine call hierarchy is not being propagated. As a result only deep most level coroutine promise is rejected, other val promises including top most one remain in a perpetual pending state.
- Propagate errors via promise rejections rather then exceptions to ensure consistent behaviour between normal and coroutine functions.
Newly added _emval_coro_reject() function calls JS Promise reject functor at the end of call hierarchy. Since the call crosses C++ JS barrier, the Signature::get_method_caller() function is called, which has thread_local variable, adding thread local storage, and therefore the requirement for the embind to be compiled with same threadness as the main program.
a380dee
to
ede5955
Compare
This is my first time contributing to the project, so I am not familiar with the process. |
___cxa_rethrow(); | ||
} catch (e) { | ||
return Emval.toHandle(e); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aheejin does this look reasonable to you? Or is the maybe a better way to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we wait for @aheejin's review or merge as-is? This piece of code was before this PR (I added it a while back because it was the only way to make it work that I found at the time), so I'm leaning towards let's merge it anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @aheejin
7150915
to
41eff7b
Compare
___cxa_rethrow(); | ||
} catch (e) { | ||
return Emval.toHandle(e); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ping @aheejin
Fix bug when failure or exception happening in a >1 level of the val coroutine call hierarchy is not being propagated. As a result only deep most level coroutine promise is rejected, other val promises including top most one remain in a perpetual pending state.
The bug can be reproduced by the following example: