diff --git a/core/libs/prx/libc/src/exception/ExceptionPointer.cpp b/core/libs/prx/libc/src/exception/ExceptionPointer.cpp index eba668749..447d85ac4 100644 --- a/core/libs/prx/libc/src/exception/ExceptionPointer.cpp +++ b/core/libs/prx/libc/src/exception/ExceptionPointer.cpp @@ -1,12 +1,23 @@ #include #ifndef _LIBCPP_VERSION +#include + extern "C" { void ExceptionPointerAddref(std::exception_ptr* self) noexcept asm("_ZNSt15__exception_ptr13exception_ptr9_M_addrefEv"); void ExceptionPointerRelease(std::exception_ptr* self) noexcept asm("_ZNSt15__exception_ptr13exception_ptr10_M_releaseEv"); void* ExceptionPointerGet(const std::exception_ptr* self) noexcept asm("_ZNKSt15__exception_ptr13exception_ptr6_M_getEv"); void ExceptionPointerConstruct(std::exception_ptr* self, void* exception) noexcept asm("_ZNSt15__exception_ptr13exception_ptrC1EPv"); const std::type_info* ExceptionPointerType(const std::exception_ptr* self) noexcept asm("_ZNKSt15__exception_ptr13exception_ptr20__cxa_exception_typeEv"); +void FutureResultDestroy(std::__future_base::_Result_base* self) noexcept asm("_ZNSt13__future_base12_Result_baseD2Ev"); + +void FutureResultDestroy(std::__future_base::_Result_base* self) noexcept { + self->_M_error.~exception_ptr(); +} + +void APS5_VABI _ZNSt13__future_base12_Result_baseD2Ev_nid_postfix(std::__future_base::_Result_base* self) noexcept { + FutureResultDestroy(self); +} void APS5_VABI _ZNSt15__exception_ptr13exception_ptr9_M_addrefEv_nid_postfix(std::exception_ptr* self) noexcept { ExceptionPointerAddref(self); diff --git a/core/libs/tests/WindowsExceptions.cpp b/core/libs/tests/WindowsExceptions.cpp index 2e13adb43..deb55e6dd 100644 --- a/core/libs/tests/WindowsExceptions.cpp +++ b/core/libs/tests/WindowsExceptions.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -105,9 +106,30 @@ static void testExceptionPointer() { if (std::current_exception()) throw std::runtime_error("stale current exception"); } +static void testFutureException() { + std::atomic count{0}; + { + std::promise promise; + auto future = promise.get_future(); + try { + throw TrackedError(&count); + } catch (const TrackedError&) { + promise.set_exception(std::current_exception()); + } + try { + future.get(); + throw std::runtime_error("future did not rethrow"); + } catch (const TrackedError& error) { + if (std::strcmp(error.what(), "retained error")) throw std::runtime_error("future rethrew another error"); + } + } + if (count != 1) throw std::runtime_error("future result destroyed its exception an incorrect number of times"); +} + int main() { TestTypeInfoVtables(); testExceptionPointer(); + testFutureException(); try { Rethrow(); return 1;