C++11 std::thread join crashes with system_error exception and SIGABRT on Xcode 6?
Asked Answered
C

3

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.
Cynth answered 21/6, 2015 at 22:53 Comment(4)
You should either call detach or join on the thread object but not bothAdductor
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?Chavey
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.Christiachristian
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.Cynth
S
9

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.

Salaidh answered 21/6, 2015 at 23:25 Comment(0)
R
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;
}
Rogovy answered 22/8, 2017 at 8:58 Comment(1)
this is the case for me , in unitest ,some thread is not scheduled but joined.Loveinamist
C
-1

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

Cynth answered 21/6, 2015 at 23:11 Comment(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.Christiachristian
⁺¹ for the interesting question, tho.Christiachristian
The resons for calling join or detach are completely unrelated to when the thread is executed.Disintegrate

© 2022 - 2024 — McMap. All rights reserved.