Thread completion: pthread_join
pthread_join
- Signature:
int pthread_join(pthread_t t, void **retval); - Blocks the caller until thread
tterminates. *retvalreceives whatever the start routine returned (avoid *).- Pass
NULLas the second arg if you don’t care about the return value.
One joiner per thread
- Each joinable thread can be joined exactly once. A second join is undefined behavior — typically returns garbage or crashes.
- Two threads concurrently joining the same target is the same bug.
- The OS won’t stop you — this is the kind of thing you need a habit to enforce, not a check at the API boundary.
Returning values out
void *worker(void *arg) {
result_t *r = malloc(sizeof *r);
r->status = OK;
return r; // void * out
}
void *raw;
pthread_join(t, &raw);
result_t *r = raw; // cast back
- The thread returns a pointer; pthread_join writes that pointer into
*retval. NULLis just(void *)0— perfectly legitimate, not “no return”.- Anything pointing at the joinee’s stack is invalid (see ch27-1).
Detach: skip the join
pthread_detach(t)tells the runtime “I won’t be joining this; clean it up yourself when it exits.”- Useful for fire-and-forget background work (logging, telemetry, request handlers that respond and forget).
- Forgetting to join a joinable thread is a resource leak; detaching upfront eliminates that whole class of bug.
Quiz yourself
- What goes wrong if two callers both try to pthread_join the same thread?
- When should you prefer pthread_detach over pthread_join?