I can reproduce the behavior you describe with your program, using glibc 2.28 and gcc 8.5.0.
This variation produces behavior more in line with what I think you expected:
// C program to show thread functions
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <semaphore.h>
sem_t sem;
void *func(void *arg) {
int x = pthread_detach(pthread_self());
sem_post(&sem);
printf("x = %d\n", x);
printf("Error description in second thread is : %s\n",strerror(x));
printf("Inside the thread\n");
pthread_exit(NULL);
}
void fun() {
pthread_t ptid;
pthread_create(&ptid, NULL, &func, NULL);
sem_wait(&sem);
int x = pthread_join(ptid, NULL);
printf("Error description in initial thread is: %s\n",strerror(x));
pthread_exit(NULL);
}
int main() {
sem_init(&sem, 0, 0);
fun();
return 0;
}
I modified the output a bit, but the main difference is that in this version, the initial thread waits to attempt to join the second one until the second signals via a semaphore that it has detached itself. This is the output I get:
x = 0
Error description in second thread is : Success
Inside the thread
Error description in initial thread is: Invalid argument
In this program, then, the pthread_join()
call returns EINVAL
, consistent with the target thread not being joinable.
This seems to reflect a race condition. Apparently, in the implementation I am testing and probably in yours as well, if pthread_join()
proceeds far enough before the target thread detaches itself, then it waits for the target thread to terminate, even though eventually that thread is detached.
Note, however, that it is erroneous in the first place to attempt to both join and detach the same thread. POSIX makes only recommendations for the behavior in such case, while leaving it formally undefined (as far as POSIX is concerned). Glibc's pthread_join
will detect the case where the target thread is already detached and fail with EINVAL
, but the documentation doesn't say anything about what happens if a thread is detached while another one is trying to join it. Erroneous behavior does not necessarily produce predictable results.