Merge pull request #2570 from oneandonlydean/fix/libc-future-result-exception-2540

fix(libc): release future results' exceptions through libc on Windows
This commit is contained in:
Dean 2026-10-10 19:51:09 +13:00 committed by GitHub
commit 6284b64fa5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 0 deletions

View File

@ -1,12 +1,23 @@
#include <exception>
#ifndef _LIBCPP_VERSION
#include <future>
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);

View File

@ -4,6 +4,7 @@
#include <atomic>
#include <array>
#include <exception>
#include <future>
#include <thread>
#include <cstddef>
#include <typeinfo>
@ -105,9 +106,30 @@ static void testExceptionPointer() {
if (std::current_exception()) throw std::runtime_error("stale current exception");
}
static void testFutureException() {
std::atomic<int> count{0};
{
std::promise<void> 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;