2

Below is the program for which I am expecting the program to go into a deadlock because pthread_join() is a blocking wait on a thread (it is waiting to terminate).

But I see that pthread_join() does not block and returns with failure (35 = EDEADLK)

Can you help me understand why pthread_join() unblocks? Because the main thread is yet to terminate and probably this should be a deadlock?

#include <stdio.h>

#include <stdlib.h>
#include <pthread.h>

int
main(int argc, char *argv[])
{
    void *res;
    int s;
    printf("Message from main()\n");

    s = pthread_join(pthread_self(), &res);
    if (s != 0)
        printf("pthread_join(): %d",s);
        
    printf("Thread returned %d\n", (int) res);
    exit(0);
}

Here is the output:

Message from main()
pthread_join(): 35
Thread returned 134514009
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • Instead of `printf("pthread_join(): %d",s);` do `{errno = s; perror("pthread_join()");}` and you might receive enlightning information. – alk Jun 07 '14 at 10:02

1 Answers1

3

You cannot join to yourself. The POSIX manpage for pthread_join specifies that you may get a deadlock error:

[EDEADLK]
    A deadlock was detected or the value of thread specifies the calling thread.

And, indeed, a search of that error shows that it's 35, at least on my system:

pax> cd /usr/include
pax> grep EDEADLK *.h */*.h */*/*.h
asm-generic/errno.h:#define EDEADLK     35  /* Resource deadlock would occur */

While some deadlocks are subtle and difficult for pthreads to automatically detect, this one is relatively easy, with something like this at the start of the join function:

int pthread_join(pthread_t thread, void **value_ptr) {
    if (thread == pthread_self())
        return EDEADLK;
    // rest of function
}
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • One might like to add, that the value of `res` (which's address had been passed to `pthread_join()`) does not carry meaningful data if `pthread_join()` failed. Moreover for this case of failure if `res` had not been initialised prior using it with `pthread_join()` (as per the OP's code snippet) printing out its value provokes undefined behaviour. – alk Jun 07 '14 at 10:05
  • As per my query, i felt it is a deadlock. Are you saying pthread_join() is intelligent enough to detect deadlock and come out? Is that the reason, am able to see 'Thread returned' statement? – overexchange Jun 07 '14 at 12:26
  • @overexchange: yes, the doco clearly states that EDEADLK is one of the possible errors if "the value of thread specifies the calling thread". Given that EDEADLK is 35 (on my system and _probably_ yours as well) and that's what you got, your implementation detects that deadlock scenario. It could be caught in the join quite easily with something like `if (passed_thread == pthread_self()) return EDEADLK;`. I'll add to the answer. – paxdiablo Jun 07 '14 at 12:42
  • @paxdiablo one additional question, i see many examples where 'pthread_join(t1,NULL);' is being used. How should i understand passing NULL to pthread_join(), Does that mean pthread_join() does not wait for thread to terminate? or Does pthread_join() wait for thread to terminate but does not capture return value? – overexchange Jun 09 '14 at 10:04
  • @overexchange: it's the latter. It still waits for the thread to finish but, since you provide nowhere for the exit value to be stored, it gets thrown away. – paxdiablo Jun 09 '14 at 10:19