llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.26k stars 12.08k forks source link

std::future<T>::get() returns while std::async(std::launch:async,...) thread is running #64883

Open gabrbedd opened 1 year ago

gabrbedd commented 1 year ago

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.

EugeneZelenko commented 1 year ago

Could you please try 17 Release Candidate or main branch? https://godbolt.org should be helpful.

gabrbedd commented 1 year ago

I could reproduce on Ubuntu 22.04.3 LTS with clang-17 and libc++-17 from apt.llvm.org/jammy . I hope that's recent enough.

Invocation

$ /usr/lib/llvm-17/bin/clang++ --stdlib=libc++ -v -o main main.cpp

Clang version

$ /usr/lib/llvm-17/bin/clang++ --version
Ubuntu clang version 17.0.0 (++20230821083344+4ec6595d6e5b-1~exp1~20230821083505.27)
Target: aarch64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-17/bin

/usr/share/doc/clang-17/changelog.Debian.gz:
llvm-toolchain-17 (1:17.0.0~++20230821083344+4ec6595d6e5b-1~exp1~20230821083505.27) experimental; urgency=medium

  [ Sylvestre Ledru ]
  * jammy New snapshot release

  [ jenkins-debian-glue Autobuilder ]
  * SNAPSHOT autobuild for unreleased
    1:17.0.0~++20230821083344+4ec6595d6e5b-1~exp1 via jenkins-debian-
    glue.

 -- jenkins-debian-glue Autobuilder <jenkins@deb-gknlj4.europe-west1-b.c.secret-envoy-319113.internal>  Mon, 21 Aug 2023 08:35:05 +0000

libc++

readlink -f /lib/aarch64-linux-gnu/libc++.so.1
/usr/lib/llvm-17/lib/libc++.so.1.0

/usr/share/doc/libc++-17-dev/changelog.Debian.gz:
llvm-toolchain-17 (1:17.0.0~++20230821083344+4ec6595d6e5b-1~exp1~20230821083505.27) experimental; urgency=medium

  [ Sylvestre Ledru ]
  * jammy New snapshot release

  [ jenkins-debian-glue Autobuilder ]
  * SNAPSHOT autobuild for unreleased
    1:17.0.0~++20230821083344+4ec6595d6e5b-1~exp1 via jenkins-debian-
    glue.

 -- jenkins-debian-glue Autobuilder <jenkins@deb-gknlj4.europe-west1-b.c.secret-envoy-319113.internal>  Mon, 21 Aug 2023 08:35:05 +0000