FranMowinckel
FranMowinckel

Reputation: 4343

Using and joining a std::thread object from different threads

This is a minimal example based on a code that was handed to me:

// Example program
#include <iostream>
#include <string>
#include <thread>


int main()
{
  std::cout << "Start main\n";
  int i = 0;
  auto some_thread = std::thread([&]() { 
     std::cout << "Start some thread\n";
      while(i++ < 100) {
        std::cout << i << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      }
  });
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));  

  auto some_thread2 = std::thread([&]() { 
      std::cout << "Start thread 2\n";
      if (some_thread.joinable()) {
        std::cout << "Thread 2 will join\n";
        some_thread.join();
        std::cout << "Thread 2 ended\n";
      } else {
        std::cout << "Thread 2 ended but didn't join\n";
      }
  });
  std::this_thread::sleep_for(std::chrono::milliseconds(1000));
  if (some_thread.joinable()) {
    std::cout << "Main will join\n";
    some_thread.join();
    std::cout << "Main ended\n";
    return 0;
  } else {
    std::cout << "Main ended but didn't join\n";
    return 1;
  }
}

In short, the full program (as in this example) access to some std::thread object from different threads and tries to join and detach to it.

I know it's a poor design, and that if you try to join a thread twice it will crash because after the first one finishes, then there's no thread associated with it. But this is not the case.

In this example it's crashing before the thread ends and with an Abort trap:6. It just prints a couple of numbers and then crashes (the thread doesn't end its execution).

The code is not mine and I don't want a redesign. I just want to understand why it's crashing.

A final note, the original code was working somehow using semaphores and such (with some random crashes, though).

Upvotes: 0

Views: 1489

Answers (2)

FranMowinckel
FranMowinckel

Reputation: 4343

The std::thread library is usually implemented on top of pthreads in an environment supporting pthreads (for example: libstdc++).

Quoting from pthread_join linux documentation:

If multiple threads simultaneously try to join with the same thread, the results are undefined.

It also mentions that it returns the following error:

EINVAL Another thread is already waiting to join with this thread.

Upvotes: 0

Praetorian
Praetorian

Reputation: 109279

I know ... that if you try to join a thread twice it will crash because after the first one finishes, then there's no thread associated with it. But this is not the case.

On the contrary, that's exactly what's going on here. some_thread2 calls some_thread.join() and while it's waiting on some_thread to exit, the main thread is also calling some_thread.join(). some_thread is still active, and hasn't been joined at the time of the two checks, so joinable() returns true in both cases.

One way to avoid the crash would be to add some_thread2.join(); before you check some_thread.joinable() in the main thread (but if you do that, there's no need for the main thread to join some_thread).

In any case, it's not clear why you want to join the thread from two different threads, so it's difficult to suggest a better solution.

Upvotes: 1

Related Questions