Skip to content

Commit 11766a4

Browse files
authored
[libc++] Don't try to wait on a thread that hasn't started in std::async (#125433)
If the creation of a thread fails, this causes an idle loop that will never end because the thread wasn't started in the first place. Fixes #125428
1 parent 0f9720a commit 11766a4

File tree

2 files changed

+64
-2
lines changed

2 files changed

+64
-2
lines changed

libcxx/include/future

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,8 @@ void __async_assoc_state<_Rp, _Fp>::__execute() {
865865

866866
template <class _Rp, class _Fp>
867867
void __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT {
868-
this->wait();
868+
if (base::__state_ & base::__constructed)
869+
this->wait();
869870
base::__on_zero_shared();
870871
}
871872

@@ -902,7 +903,8 @@ void __async_assoc_state<void, _Fp>::__execute() {
902903

903904
template <class _Fp>
904905
void __async_assoc_state<void, _Fp>::__on_zero_shared() _NOEXCEPT {
905-
this->wait();
906+
if (base::__state_ & base::__constructed)
907+
this->wait();
906908
base::__on_zero_shared();
907909
}
908910

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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, no-exceptions
10+
11+
// ASan seems to try to create threadsm which obviouly doesn't work in this test.
12+
// UNSUPPORTED: asan
13+
14+
// UNSUPPORTED: c++03
15+
16+
// There is no way to limit the number of threads on windows
17+
// UNSUPPORTED: windows
18+
19+
// AIX and macOS seem to limit the number of processes, not threads via RLIMIT_NPROC
20+
// XFAIL: target={{.+}}-aix{{.*}}
21+
// XFAIL: target={{.+}}-apple-{{.*}}
22+
23+
// This test makes sure that we fail gracefully in care the thread creation fails. This is only reliably possible on
24+
// systems that allow limiting the number of threads that can be created. See https://llvm.org/PR125428 for more details
25+
26+
#include <cassert>
27+
#include <future>
28+
#include <system_error>
29+
30+
#if __has_include(<sys/resource.h>)
31+
# include <sys/resource.h>
32+
# ifdef RLIMIT_NPROC
33+
void force_thread_creation_failure() {
34+
rlimit lim = {1, 1};
35+
assert(setrlimit(RLIMIT_NPROC, &lim) == 0);
36+
}
37+
# else
38+
# error "No known way to force only one thread being available"
39+
# endif
40+
#else
41+
# error "No known way to force only one thread being available"
42+
#endif
43+
44+
int main(int, char**) {
45+
force_thread_creation_failure();
46+
47+
try {
48+
std::future<int> fut = std::async(std::launch::async, [] { return 1; });
49+
assert(false);
50+
} catch (const std::system_error&) {
51+
}
52+
53+
try {
54+
std::future<void> fut = std::async(std::launch::async, [] { return; });
55+
assert(false);
56+
} catch (const std::system_error&) {
57+
}
58+
59+
return 0;
60+
}

0 commit comments

Comments
 (0)