6

Here is a simple thread trace program. The thread simply prints the first ten integers and then the "thread is done" message.

#include <iostream>
#include <vector>
#include <numeric>
#include <thread>

void f();

int main(int argc, const char * argv[]) {
    std::thread t(f);

    std::cout << "Thread start" << std::endl;

    t.detach();
    t.join();

    std::cout << "Thread end" << std::endl;

    return 0;
}

void f()
{
    std::vector<int> a(10);
    std::iota(a.begin(), a.end(), 0);

    for(const int& i : a)
    {
        std::cout << i << std:: endl;
    }
    std::cout << "Thread is done." << std::endl;
}

However, when it runs, t.join throws a std::__1::system_error exception, somewhere in the libc ABI, leading the program to terminate with SIGABRT:

Thread start
0
1
2
3
4
5
6
7
8
9
Thread is done.
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: thread::join failed: No such process

Sometimes when it runs the exception in the main thread occurs (at the same place) before thread t runs (but it still does):

Thread start
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: thread::join failed: No such process
0
1
2
3
4
5
6
7
8
9
Thread is done.
4
  • You should either call detach or join on the thread object but not both Commented Jun 21, 2015 at 23:01
  • 1
    Where did you get the idea of doing both detach and join? Are you just calling every method that pops up in the code completion without reading any documentation?
    – DanielKO
    Commented Jun 21, 2015 at 23:02
  • Folks, it is interesting anyway why is the abort happens. I couldn't yet find where is the prohibition defined except of just logical reasoning.
    – Hi-Angel
    Commented Jun 21, 2015 at 23:03
  • I didn't see previously see anywhere in the documentation that a thread is automatically started on construction. I thought that's what detach was for. Commented Jun 21, 2015 at 23:04

3 Answers 3

8

The issue is that both detach and join have a precondition that the thread is joinable, and both have as a post condition that joinable is false. This means that once you call one on a thread, attempting to call the other is invalid.

Secondly, the differing behavior you are seeing is due the timing of the execution of the thread and the main function. Sometimes the detach and join don't execute till after the thread runs, sometimes they run before, and anything in between.

4

Could be the result of trying to join threads that weren't started.

I was getting this error when I was joining an array for threads like this:

for (auto& th : threads) th.join();

Then I re-wrote with a manual for loop which gave me no errors:

for (i = 0; i< numthreads; i++)   
        threads[i] = thread(start,i+1);

I think it's because I declared the array like this:

    std::thread threads[MAXTHREADS];

And so it was trying to join threads I hadn't started.

Full code for reference:

#include <sched.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <thread>         // std::thread
#include <mutex>          // std::mutex

using namespace std;
mutex mtx;           // mutex for critical section

#define MAXTHREADS 10
#define MAXTIMES 1

int data[MAXTHREADS];

int start(int id) {

    int stride = 64, dummy;
    mtx.lock();
    for(int times = 0; times < MAXTIMES; times++) {
        for (int i = 0; i < MAXTHREADS; i = i + 1) {
            //dummy = data[i]; //sim a read from every slot in the array
            cout << data[i] << ", ";
        }
        cout << endl;
    }
    mtx.unlock();
    return 0;
}

int main()
{
    std::thread threads[MAXTHREADS];
    int i;
    int numthreads = 6;

    for(int i = 0; i < MAXTHREADS; i++) 
        data[i] = i;


    printf("Creating %d threads\n", numthreads);

    for (i = 0; i< numthreads; i++)
        threads[i] = thread(start,i+1);

    for (i = 0; i< numthreads; i++)
        threads[i].join();

    //for (auto& th : threads) th.join();
    printf("All threads joined\n");

    return 0;
}
1
  • this is the case for me , in unitest ,some thread is not scheduled but joined.
    – FaceBro
    Commented Aug 19, 2019 at 8:59
-1

A std::thread begins execution after construction. Thus detach is not necessary.

3
  • Sorry, but I am voting the answer down, and still wait for another one. The thing you told would be obvious from the documentation, while the question, where's the prohibition to call join() after detach() defined is the more interesting, and unanswered here.
    – Hi-Angel
    Commented Jun 21, 2015 at 23:15
  • ⁺¹ for the interesting question, tho.
    – Hi-Angel
    Commented Jun 21, 2015 at 23:31
  • The resons for calling join or detach are completely unrelated to when the thread is executed.
    – MikeMB
    Commented Jun 22, 2015 at 8:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.