In the call pthread_create(&id, NULL, &start_routine, arg), is the thread id guaranteed to be written to id before start_routine starts running? The manpages are clear that the start_routine may but will not necessarily begin executing before the call to pthread_create returns, but they are silent on when the thread id gets written back to the passed thread argument.
My specific case is that I have a wrapper around pthread_create:
int mk_thread(pthread_t *id) {
pthread_t tid;
pthread_create(&tid,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
} else {
*id=lid;
}
}
which can obviously run the start routine before writing back. I changed it to
int mk_thread(pthread_t *id) {
pthread_t tid,tidPtr=id?id:&tid;
pthread_create(tidPtr,NULL,ThreadStart,NULL);
if (id == NULL) {
pthread_detach(tid);
}
}
This rewrite is much more stable in practice, but is it actually a fix or just a smaller window for the race condition?
The thread id is definitely written before
pthread_createreturns. If you think about it, it would be impossible forpthread_createto work any other way. It could not delegate writing the thread id to the new thread, because thepthread_tvariable might be out of scope by the time the new thread runs.The relevant text is:
(From http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_create.html) Note that it says “on successful completion” of the function, not “at an indeterminate time after successful completion”.
The more interesting question, and I’m unclear on this one, is whether
pthread_createmust have finished writing the thread id to its destination before the new thread start function begins, i.e. whether the new thread can immediately see its own thread id, e.g. if it’s to be stored in a global variable. I suspect the answer is no.Edit: Upon rereading your question, it seems like you might really have been asking about this latter, more interesting question. In any case, there’s no reason for the new thread’s start function to use the thread-id written out by
pthread_create. Your new thread can (and should) just usepthread_selfto get its own thread id.