diff --git a/libcxx/include/future b/libcxx/include/future index c17e79f8c03bc..977273e396c1e 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -865,7 +865,8 @@ void __async_assoc_state<_Rp, _Fp>::__execute() { template void __async_assoc_state<_Rp, _Fp>::__on_zero_shared() _NOEXCEPT { - this->wait(); + if (base::__state_ & base::__constructed) + this->wait(); base::__on_zero_shared(); } @@ -902,7 +903,8 @@ void __async_assoc_state::__execute() { template void __async_assoc_state::__on_zero_shared() _NOEXCEPT { - this->wait(); + if (base::__state_ & base::__constructed) + this->wait(); base::__on_zero_shared(); } diff --git a/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp b/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp new file mode 100644 index 0000000000000..9ab8296d49af1 --- /dev/null +++ b/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// UNSUPPORTED: no-threads, no-exceptions + +// ASan seems to try to create threadsm which obviouly doesn't work in this test. +// UNSUPPORTED: asan + +// UNSUPPORTED: c++03 + +// There is no way to limit the number of threads on windows +// UNSUPPORTED: windows + +// AIX and macOS seem to limit the number of processes, not threads via RLIMIT_NPROC +// XFAIL: target={{.+}}-aix{{.*}} +// XFAIL: target={{.+}}-apple-{{.*}} + +// This test makes sure that we fail gracefully in care the thread creation fails. This is only reliably possible on +// systems that allow limiting the number of threads that can be created. See https://llvm.org/PR125428 for more details + +#include +#include +#include + +#if __has_include() +# include +# ifdef RLIMIT_NPROC +void force_thread_creation_failure() { + rlimit lim = {1, 1}; + assert(setrlimit(RLIMIT_NPROC, &lim) == 0); +} +# else +# error "No known way to force only one thread being available" +# endif +#else +# error "No known way to force only one thread being available" +#endif + +int main(int, char**) { + force_thread_creation_failure(); + + try { + std::future fut = std::async(std::launch::async, [] { return 1; }); + assert(false); + } catch (const std::system_error&) { + } + + try { + std::future fut = std::async(std::launch::async, [] { return; }); + assert(false); + } catch (const std::system_error&) { + } + + return 0; +}