19

I want to store a collection of threads in a vector, and join them all before exiting my program. I receive the following error when trying to join the first thread no matter how many I place in the collection:

system_error: thread::join failed: No such process

Here is some simple code that demonstrates my issue:

#include <thread>
#include <iostream>
#include <vector>
#include <functional>

using std::cout;
using std::endl;
using std::vector;
using std::thread;
using std::mem_fn;

int main()
{
  vector<thread> threads(1);
  threads.push_back(thread([]{ cout << "Hello" << endl; }));
  for_each(threads.begin(), threads.end(), mem_fn(&thread::join));

  // also tried --> for(thread &t : threads) t.join()
}

And I'm building it using the following (tried clang++ 4.2.1 and g++ 5.3.1):

g++ -o src/thread_test.o -c -std=c++14 src/thread_test.cpp -pthread
g++ -o thread_test src/thread_test.o -pthread

I see lots of examples doing just this around the internet. Did something change in the contract of <thread> or <vector> that's rendered these examples defunct?

NOTE: As an aside for future readers, I ended up adding the (1) constructor argument after trying {} assignment, which fails due to a private copy constructor. In trying to avoid the copy constructor I ended up allocating uninitialized threads -- careless mistake.

Andreas
  • 5,086
  • 3
  • 16
  • 36
Rich Henry
  • 1,837
  • 15
  • 25
  • 1
    Please use the `-pthread` compiler flags for both compiling and linking stage, rather than linking `-lpthread`. – πάντα ῥεῖ Jun 30 '16 at 18:31
  • I'm using scons, so it formats my library arguments for me. It actually works without either -pthread or -lpthread and I had added it just to make sure I wasn't missing some implementation detail during my troubles. So 1) i think the compiler is adding those flags for me silently, and 2) why is the nonstandard lib include preferable? – Rich Henry Jun 30 '16 at 18:34
  • 3
    `-lpthread` is a direct request to the linker whereas `-pthread` is an option interpreted by the compiler driver. If you use `-pthread` consistently at both compile and link time, that gives the compiler driver the opportunity to do anything _else_ that may be required, besides linking in libpthread, to make a multithread-capable program. That said, I haven't tripped over a system where anything else was actually necessary in many years. – zwol Jun 30 '16 at 19:44
  • Hopefully moving forward we won't need to refer to pthreads at all, and a modern compiler will select the appropriate implementation of `` for our platform. – Rich Henry Jun 30 '16 at 19:50

1 Answers1

34

vector<thread> threads(1);

This creates a thread which can be accessed at index 0.

threads.push_back(thread([]{ cout << "Hello" << endl; }));

This adds a second thread which can be accessed at index 1.

for_each(threads.begin(), threads.end(), mem_fn(&thread::join));

This is going to call join on both thread objects. However, the first one was never started therefore it is not joinable.

Instead, you could replace vector<thread> threads(1); with vector<thread> threads; threads.reserve(1); and keep using push_back.

James Adkison
  • 9,412
  • 2
  • 29
  • 43
  • Thank you, thank you! This was exactly my problem. Instead of: `vector threads; threads.reserve(size);` I found this slightly more readable and self-explaining: `vector threads(size); threads.clear();` But I put a link to this post in a comment too. – Craig Reynolds Mar 29 '20 at 18:41