3

I am checking the behavior of 'pthread_join' and have the following code:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>

#include <pthread.h>

void *thread(void *vargp)
{
    pthread_detach(pthread_self());
    pthread_exit((void *)42);
}

int main()
{
    int i = 1;
    pthread_t tid;

    pthread_create(&tid, NULL, thread, NULL);

    sleep(1);
    pthread_join(tid, (void **)&i);
    printf("%d\n", i);
    printf("%d\n", errno);
}

Observed output on my platform (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):

  1. with the 'sleep(1)' commented out: 42 0

  2. with the sleep statement, it produces: 1 0

according to the man page of pthread_join, we should get the error 'EINVAL' when we are trying to join a non-joinable thread, however, neither cases above got the errno set. And also in the first case, it seemed that we can even get the exit status of a detached thread, I am confused with the result. Could anyone explain this? Thanks

[EDIT]: I realized that the first printf may reset 'errno', however, even after I swapped the order of the two 'printf' statements, I still got the same results.

alk
  • 69,737
  • 10
  • 105
  • 255
chuchao333
  • 1,438
  • 1
  • 14
  • 22
  • The case you describe is allowed by POSIX. Perhaps the manpage is outdated. (PS. I mean case 1). – chill Dec 17 '12 at 16:33
  • Also knowing the results of the call to `pthread_detach()` for both the cases would be interesting. – alk Dec 17 '12 at 16:58
  • For case 2 using Debian (stable) I'm getting `errno==EINVAL`. – alk Dec 17 '12 at 17:11
  • @chill Do you have any citation for this statment? – alk Dec 17 '12 at 17:18
  • @alk are you saying that in case 1 you also couldn't get the errno set? That's even more confusing :( I think we need someone guide us to some authoritative/official POSIX pthread specifications. – chuchao333 Dec 17 '12 at 17:24
  • @chuchao333: For case 1 no errors (the result is 0) are logged. Please not that I'm using the results returned by the `pthread_*` functions, not the value held by `errno`. – alk Dec 17 '12 at 17:26

2 Answers2

5

Your expectation is wrong. Calling pthread_join on a detached thread invokes undefined behavior. There is no requirement to set errno, return the error code, or even return at all.

In case you need a citation,

The behavior is undefined if the value specified by the thread argument to pthread_join() does not refer to a joinable thread.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_join.html

Also, note that most pthread functions, including pthread_join, do not use errno. Instead they return the error code as their return value. As such, inspecting errno after calling a pthread function is wrong even if you didn't invoke undefined behavior when you called it.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • I have the exactly the same man page as in this link: http://www.kernel.org/doc/man-pages/online/pages/man3/pthread_join.3.html is that outdated? Where can I get the latest/correct one? – chuchao333 Dec 17 '12 at 17:15
  • I would say the Linux man pages are just ambiguous, not outright wrong or outdated. In the first paragraph of the description, it says: "The thread specified by thread must be joinable." This is different from saying "If the thread is not joinable, an error results." But even if it said the latter, you still wouldn't be safe making the call, because **any** use of the `pthread_t` value for a detached thread after it has exited invokes undefined behavior. – R.. GitHub STOP HELPING ICE Dec 17 '12 at 17:38
  • Nonetheless, I would agree the Linux man pages should be improved to be more clear. Part of the problem arises from a bug in the previous version of POSIX, which listed lots of nonsensical error returns for pthread functions when the error could not happen except in the case that undefined behavior had already been invoked (in which case, the text about the error need not be followed). This was reported as a bug in the specification, and fixed in POSIX 2008. You'll see in the page I linked, at the very bottom, text about the wrong errors being removed. – R.. GitHub STOP HELPING ICE Dec 17 '12 at 17:41
0

You get this error by reading the return value of function pthread_join, try this:

if (errno = pthread_join(tid,NULL)) {
    printf("An error ocurred: %i", errno);
}
Aljana Polanc
  • 950
  • 8
  • 12
  • I still got 'errno' as 0 by getting the return value. It seems that the pthread_join call was considered as success. – chuchao333 Dec 17 '12 at 16:49
  • Better do: `int result = pthread_join(...; if (result) printf(..., result);` – alk Dec 17 '12 at 17:14
  • 1
    It's still invalid because OP is invoking UB trying to join a detached (and terminated) thread. BTW, there's probably never any need to check the return value of `pthread_join` since the only failures are UB or programming errors, not environmental/runtime errors. – R.. GitHub STOP HELPING ICE Dec 17 '12 at 17:43