How do I get the error code from pthread_join()?

Celeritas picture Celeritas · Oct 10, 2013 · Viewed 7.5k times · Source

The following code fails to join pthreads and the message "join failed" is printed. How do I get more information about the failure and its cause?

pthread_t aThread[MAX_LENGTH];
    int errCode[MAX_LENGTH];
    char returnVal;    
for(int i = 0; i < MAX_LENGTH; i++)
    {

        if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
            printf("error creating thread %d\n", errCode[i]);
        if(!pthread_join(aThread[i], (void**)&returnVal))
            printf("join failed\n i is %d", i);
    }

EDIT: actually join returned no error and I made a mistake. The if statment shouldn't have the ! because join returns a non-zero number if there is a problem which evaluates to true.

Answer

WhozCraig picture WhozCraig · Oct 10, 2013

I pointed this out in comment, but it deserves amplification.

Your returnVal usage is wrong

The pthread_join api expects a void**, that is a pointer to a void*. Unlike void*, a void** is not equally universal. It is a pointer of specific type and as such you should only pass a likewise typed address. However, you're not using it anyway, so I would suggest for now you simply pass NULL. As-written, it is undefined behavior. And I can all-but-guarantee you sizeof(char), the writable size of the address you giving it, and sizeof(void*), the size it expects to have available, are not the same. Consider this instead for now:

pthread_join(aThread[i], NULL);

In case you're wondering what the use for that void** parameter is, it is a place to store void* return value from your thread-proc. Recall a pthread thread-proc looks like this:

void* thread_proc(void* args)
// ^----- this is what is stashed in the pthread_join second parameter

You're logic for failure testing is backwards

The pthread_join function returns 0 on success; not on failure.


You're not actually running concurrent threads

Thread concurrency simply means your threads run simultaneously. But yours do not. You start a thread, then wait for it to end, then start a thread, then wait for it to end, etc. This is literally no better (and in fact, actually worse) than simply calling a function. If you want your threads to run concurrently your logic should be styled like this:

pthread_t aThread[MAX_LENGTH];
int errCode[MAX_LENGTH] = {0};

for (int i = 0; i < MAX_LENGTH; i++)
{
    if((errCode[i] = pthread_create(&aThread[i], NULL, &findMatch, &fpArgs)) != 0)
        printf("error creating thread %d, error=%d\n", i, errCode[i]);
}

for (int i = 0; i < MAX_LENGTH; i++)
{
    // note the check for errCode[i], which is only non-zero 
    //  if the i'th thread failed to start
    if(errCode[i] == 0)
    {
        errCode[i] = pthread_join(aThread[i], NULL))
        if (errCode[i] != 0)
            printf("error joining thread %d, error=%d\n", i, errCode[i]);
    }
}