[libcxx-commits] [libcxx] [libc++] Throw future_error in future.get() (PR #179409)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Apr 23 01:35:42 PDT 2026
https://github.com/Ekkorus101 updated https://github.com/llvm/llvm-project/pull/179409
>From 179c9d396e43f3c1daf5d0730e4a8b5b7fb7c390 Mon Sep 17 00:00:00 2001
From: zhangqingchun <zhangqingchun at bytedance.com>
Date: Tue, 3 Feb 2026 15:45:06 +0800
Subject: [PATCH 1/2] throw future_error in future.get()
fix segfault when we call future.get() twice, it's future_error in
libstdc++ and recommended throw future_error in cppref
---
libcxx/include/future | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/include/future b/libcxx/include/future
index 4084148e52af6..472aa7f9adefb 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -985,6 +985,9 @@ future<_Rp>::~future() {
template <class _Rp>
_Rp future<_Rp>::get() {
+ if (__state_ == nullptr) [[unlikely]] {
+ __throw_future_error(future_errc::no_state);
+ }
unique_ptr<__shared_count, __release_shared_count> __guard(__state_);
__assoc_state<_Rp>* __s = __state_;
__state_ = nullptr;
>From 13bc61892520c27882590708b8592904f686ff05 Mon Sep 17 00:00:00 2001
From: zhangqingchun <zhangqingchun at bytedance.com>
Date: Thu, 23 Apr 2026 16:15:26 +0800
Subject: [PATCH 2/2] add future error for std::future::get()
---
libcxx/include/future | 7 +-
libcxx/src/future.cpp | 2 +
.../futures.unique_future/get.pass.cpp | 69 +++++++++++++++++++
3 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/future b/libcxx/include/future
index 350117b2e5120..3874d1036857f 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -985,9 +985,8 @@ future<_Rp>::~future() {
template <class _Rp>
_Rp future<_Rp>::get() {
- if (__state_ == nullptr) [[unlikely]] {
- __throw_future_error(future_errc::no_state);
- }
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __guard(__state_);
__assoc_state<_Rp>* __s = __state_;
__state_ = nullptr;
@@ -1055,6 +1054,8 @@ future<_Rp&>::~future() {
template <class _Rp>
_Rp& future<_Rp&>::get() {
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __guard(__state_);
__assoc_state<_Rp&>* __s = __state_;
__state_ = nullptr;
diff --git a/libcxx/src/future.cpp b/libcxx/src/future.cpp
index 7bba635e9006f..ad9ec2ef01a3d 100644
--- a/libcxx/src/future.cpp
+++ b/libcxx/src/future.cpp
@@ -132,6 +132,8 @@ future<void>::~future() {
}
void future<void>::get() {
+ if (__state_ == nullptr)
+ std::__throw_future_error(future_errc::no_state);
unique_ptr<__shared_count, __release_shared_count> __(__state_);
__assoc_sub_state* __s = __state_;
__state_ = nullptr;
diff --git a/libcxx/test/std/thread/futures/futures.unique_future/get.pass.cpp b/libcxx/test/std/thread/futures/futures.unique_future/get.pass.cpp
index 65f3d2199ccdd..1a97a406835d1 100644
--- a/libcxx/test/std/thread/futures/futures.unique_future/get.pass.cpp
+++ b/libcxx/test/std/thread/futures/futures.unique_future/get.pass.cpp
@@ -152,5 +152,74 @@ int main(int, char**)
#endif
}
+
+#if defined(_LIBCPP_VERSION) && !defined(TEST_HAS_NO_EXCEPTIONS)
+ {
+ std::future<int> f;
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<int> p;
+ std::future<int> f = p.get_future();
+ p.set_value(3);
+ f.get();
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::future<int&> f;
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<int&> p;
+ std::future<int&> f = p.get_future();
+ int j = 5;
+ p.set_value(j);
+ f.get();
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::future<void> f;
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+ {
+ std::promise<void> p;
+ std::future<void> f = p.get_future();
+ p.set_value();
+ f.get();
+ try {
+ f.get();
+ assert(false);
+ } catch (const std::future_error& e) {
+ assert(e.code() == std::make_error_code(std::future_errc::no_state));
+ }
+ }
+#endif
+
return 0;
}
+
More information about the libcxx-commits
mailing list