<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/64883>64883</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
std::future<T>::get() returns while std::async(std::launch:async,...) thread is running
</td>
</tr>
<tr>
<th>Labels</th>
<td>
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
gabrbedd
</td>
</tr>
</table>
<pre>
While using `std::async(std::launch::async, )`, the returned future will become unblocked while the remote thread is still accessing shared resources. However, it should "block until the associated thread has completed, as if joined, or else time out."
### Versions
libc++: 15.00.65.0 (Mac OS, aarch64) and 15.0.7 (Fedora, x86_64)
clang++: 14.0.3 (Mac OS, aarch64) and 15.0.7 (Fedora, x86_64)
### Example Code
```
// clang++ -std=c++17 -stdlib=libc++ -o main main.cpp
#include <pthread.h>
#include <cassert>
#include <future>
#include <memory>
class delete_in_main {
public:
explicit delete_in_main(pthread_t bound_thread) : main_thread_(bound_thread) {}
~delete_in_main() {
auto this_thread = pthread_self();
assert(pthread_equal(this_thread, main_thread_) != 0);
}
private:
pthread_t main_thread_;
};
class only_copies {
public:
only_copies() = default;
explicit only_copies(std::shared_ptr<delete_in_main> o) : obj_(o) {}
only_copies(const only_copies& o) = default;
only_copies& operator=(const only_copies& o) = default;
only_copies(only_copies&& o) : obj_{o.obj_} {};
only_copies& operator=(only_copies&& o) {
obj_ = o.obj_;
return *this;
}
private:
std::shared_ptr<delete_in_main> obj_;
};
void run_test() {
pthread_t this_thread = pthread_self();
std::future<only_copies> fut = std::async(
std::launch::async,
[&]() {
only_copies iii(std::make_shared<delete_in_main>(this_thread));
return iii;
});
fut.get();
}
int main() {
for (;;) {
run_test();
}
return 0;
}
```
### Example Output
```
$ time ./main
main: main.cpp:13: delete_in_main::~delete_in_main(): Assertion `pthread_equal(this_thread, main_thread_) != 0' failed.
Aborted (core dumped)
real 0m13.301s
user 0m2.933s
sys 0m7.604s
```
Note: I haven't seen it take longer than 1 minute.
### Other notes
A work-around for this specific test case is to `std::move()` the shared pointer in the move operators.
On assert, there are usually 3 threads running.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykV0tz4zYM_jX0BRONRPohH3xw4mTaQ5tDO-3RQ5GwxQ1Fqnwkm0t_e4eS_JDiTbfdjMaRSOAj-AEEQO69OhrEDVnck8VuxmOordsceeUqlHJWWfm--bNWGiF6ZY5AlrkPkrAtYVvu340gtDwPaB6NqEeTD0Domizz9BZqBIchOoMSDjFEh_CmtIYKhW0Qoqm0FS8o4a1bsZdvbEivDrkE5cGHpMGFQN8Z5GvuUIJDb6MT6DP4yb7hK7q0ogrgaxu1BEJpBw7RBKU7aO69FYoHlCf4mnsQtmk1BpRJn3tQB_hilem_rQPUHiGoBsHGkBFKSb4j-Xb4pax_4A90Xlnjr2e1qgSh9-lhWygWWZ5ny0WWA6HlL1zA82_dmtyJejkndA3cyE4sWyWRJ5TW8STytVzuO4keV2hujhdgKOZZnrEfRZ3u6PErT8zAg5U4kljmwzMoPBH6BFc2wV0XILth78WqG9CqImx3oQTuLDRcme4nE217Xl8ZoaNEIOyh7R2V1YQ9Tqy8khLce3ThIjOa7QPvG5MNNta9T9CF5t6DxBQWe2X2nZlkdd_PtrHSSqSg7z4BAPBrq5VQYaJDaDlsYB-gstHIff-ZvJI8l4SGoT2h5QeR1T1Z7YZl_v6AfRI5m5H-eAwWQq38gAOE7eBkhUd96BUJO-kN3F1Mxb8i14SWVyApWsa2roHQIkHnI7CzuQNVTr3ygCOuLoyMEE8QCeH8fuUNa_T7XthWof_UFVdyJ4rYDiQeeNThYui108Yq5-TWJ5p9GxxhDxPy2SPYkxNt9SU5z049Nqw0RhfW-MmKyxPUbTOnsi06HqwjbPfjcOVY80p52Nbq3mb9y-60t--27VvY54hNwJ2dwxpsEsp96QBCtykUR9P_Fmff7cTrdT-G3qtVElw0-4A-fDhxl0j-D-ftsoezjacE9XDNGHtMFbND-1B_xzR9Wo3Hoqno0yVZ7D7s5fp4KaWuz0HDX3Df83iLw2mmWI8SwuDDBDl1b6L7JjGHGLIjhilxY5cr0yeQW3nwYF2qdEmV3d_MkmOffhZaV4GY37BlUgu_UUKfY2hj-LSIzvseIyP0qS833XjP8fZSI9m2YGlg6obkqJsVIglvuxSvrEnd3P9O8ys4cKVRZr1p28q61Ep1WcghyNi0KCfdhEOuE4N5U7CM5cXQHkWPrh-m2ZqxYdS_e8ibVbbM5_4Ten-13UmHn6Hmr2gIXQXwiCY1f4G_IGhrjugg1NxAAY0yMWB220HPoUYHxgYcNW5beLPu5Y67VJC7cEosgW9RqIMSkEIHBPeYGtRgR01yY19xoH6Zd33n0LG2VpmADpTpRpPcOWP6kX3P5lyVuybaIXCXGvLItX4HNrSvPoWxUeaYzeSGyTVb8xluiuWaLhfr-WIxqzfr4oCslJSKQ4ErVlYFHkopF2x-KOQhX8zUhuaU5SUtKCvyxSKbr4syX88XnPFyzRgn8xwbrnSm9WuTWXecKe8jbpbzsmQzzSvU_nSZcJskdFfFoyfzXCsf_EUtqKBx8zHp_Z5ySDd0PvPDgfPDteA77h-ndJdlWdK_3B4GhmbR6U0dQuuTYtexHlWoY5UJ2xD6lKwc_t21zn5BEQh96nbqCX3qNvtPAAAA___95eHR">