Balint Bertalan
Balint Bertalan

Reputation: 53

std::thread join() throws "std::system_error No such process" after joining with pthread

I am trying to simulate the boost::thread's timed_join functionality (I know it's deprecated) with calling pthread_timedjoin_np on the native_handle of an std::thread. The problem is that despite joinable() returns true, the join() function throws.

#include <thread>
#include <chrono>
#include <iostream>

int main()
{

    auto t = std::thread([]{
        std::this_thread::sleep_for(std::chrono::milliseconds{100});

        std::cout << "hello from thread\n";
    });

    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);

    ts.tv_sec += 1;

    if (int s = pthread_timedjoin_np(t.native_handle(), nullptr, &ts); s != 0)
    {
        std::cout << "timed out: " << s << std::endl;
    }

    if(t.joinable())
    {
        std::cout << "thread is joinable\n";
        t.join();
    }

    return 0;
}

Everything works if the spawned std::thread is still running when the pthread_timedjoin_np gets called and timed outs of course. Why is this strange behaviour? Isn't it possible to "manipulate" std::thread through its native handle?

Upvotes: 1

Views: 626

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473447

If you go behind std::thread's back with native_handle, the standard library has no idea you've done this. Therefore, the result of thread::joinable is not reliable. Or more accurately, "implementation-defined". The implementation might check if the handle has been joined. Or it might not.

So if you intend to manipulate a thread outside of the standard library's control, you need to commit to it. The simplest way would be to have your pthread_timedjoin_np condition detach the thread object if it successfully joined.

Upvotes: 2

Related Questions