Skip to content

std::async in future does not throw system_error as required (libc++) #125428

@slotosch

Description

@slotosch

During the qualification of the C++ STL for safety we run into a corner case, which seam to be a clear, safety relevant bug (violation of requriements) and error handling is very safety critical. We found it in C++14, but it is also present in current version.
The C++14 requirement in 30.6.8 states for
Functions std::async
template <class F, class... Args>
future<result_of_t<decay_t(decay_t...)>> async(F&& f, Args&&... args);

template <class F, class... Args>
future<result_of_t<decay_t(decay_t...)>> async(launch policy, F&& f, Args&&... args);
Requirement 30.6.8-6,7

6 Throws: system_error if policy == launch::async and the implementation is unable to start a new thread.

7 Error conditions:
resource_unavailable_try_again — if policy == launch::async and the system is unable to start a new thread.

Steps to reproduce:

Set limit of threads using 
Linux, MacOS: setrlimit(RLIMIT_NPROC, lim)
QNX: setrlimit(RLIMIT_NTHR, lim)

Note 1: Use RLIMIT_NTHR for the number of threads per process on QNX. Linux and MacOS (pthread) does not support RLIMIT_NTHR and control the total number of Linux threads/processes with RLIMIT_NPROC. QNX has different threading model.

Note 2. Use reasonable limit numbers. Request the current limits first and do not exceed the current rlim_cur value.
Call async function with std::launch::async policy multiple times, more then rlim_cur value.

Expected behavior:

The function throws std::system_error exception which application may catch.

Actual behavior:

Application hangs.

Issue analysis:
In gcc (linux) the exception message is reported correctly.

Also a related bug report is found in another project. However it seems not reported to the LLVM development.
emscripten-core/emscripten#8988

Workaround (big pain!):
Control the number of active threads created with async call and do not exceed the limits.

** Example to reproduce (using attached async_ex.txt)
async_ex.txt

See the difference in GNU libstdc++ and LLVM libc++ using Linux:
clang++ -stdlib=libc++ -o async_ex async_ex.txt
./async_ex
This hangs

clang++ -stdlib=libstdc++ -o async_ex async_ex.txt
./async_ex
Output:
Expected exception: Resource temporarily unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.threadingissues related to threading

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions