Skip to content

Commit 8e7f5c5

Browse files
committed
[libc++] Fix std::future not waiting until the thread is finished to clean up
1 parent abf9c1a commit 8e7f5c5

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

libcxx/include/future

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1829,7 +1829,16 @@ template <class _Rp, class _Fp>
18291829
_LIBCPP_HIDE_FROM_ABI future<_Rp> __make_async_assoc_state(_Fp&& __f) {
18301830
unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> __h(
18311831
new __async_assoc_state<_Rp, _Fp>(std::forward<_Fp>(__f)));
1832-
std::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach();
1832+
#if _LIBCPP_HAS_EXCEPTIONS
1833+
try {
1834+
#endif
1835+
std::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach();
1836+
#if _LIBCPP_HAS_EXCEPTIONS
1837+
} catch (...) {
1838+
__h->__make_ready();
1839+
throw;
1840+
}
1841+
#endif
18331842
return future<_Rp>(__h.get());
18341843
}
18351844

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// UNSUPPORTED: no-threads
10+
// UNSUPPORTED: c++03
11+
12+
// This test uses std::atomic interfaces that are only available in C++20
13+
// UNSUPPORTED: c++11, c++14, c++17
14+
15+
// Make sure that the `future` destructor keeps the data alive until the thread finished. This test fails by triggering
16+
// TSan. It may not be observable by normal means.
17+
18+
#include <atomic>
19+
#include <future>
20+
#include <mutex>
21+
22+
std::mutex mux;
23+
24+
int main() {
25+
using namespace std::chrono_literals;
26+
std::scoped_lock lock(mux);
27+
std::atomic<bool> in_async = false;
28+
auto v = std::async(std::launch::async, [&in_async, value = 1]() mutable {
29+
in_async = true;
30+
in_async.notify_all();
31+
std::scoped_lock thread_lock(mux);
32+
value = 4;
33+
(void)value;
34+
});
35+
in_async.wait(true);
36+
}

0 commit comments

Comments
 (0)