How to Use the pthread_join Function in C
-
Use the
pthread_join
Function to Wait for Thread Termination -
Use the
pthread_join
Function Return Value to Check for Errors
This article will explain several methods of how to use the pthread_join
function in C.
Use the pthread_join
Function to Wait for Thread Termination
A program creates threads with the pthread_create
function, and usually, it waits for them to terminate with the pthread_join
function. pthread_join
takes only two arguments: thread id to specify the waited thread and pointer to void*
where exit status of the specified thread can be stored. If the user does not want to retrieve the exit code of the waited thread, NULL
value should be passed as the second argument. In the following example, we demonstrate the program that creates 8 threads and executes the printHello
function in each of them. Then, the calling thread waits for every thread with the pthread_join
call in the loop. Notice that we also store the exit status code of threads in the retval
variable and print its value by casting it to int
. Mind though, if the thread gets canceled, the PTHREAD_CANCELED
value is placed at the retval
address.
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 8
#endif
void *printHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello from thread %ld, pthread ID - %lu\n", tid, pthread_self());
return NULL;
}
int main(int argc, char const *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t = 0; t < NUM_THREADS; t++) {
rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
if (rc) {
printf("ERORR; return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
int ret;
for (t = 0; t < NUM_THREADS; t++) {
void *retval;
ret = pthread_join(threads[t], &retval);
if (retval == PTHREAD_CANCELED)
printf("The thread was canceled - ");
else
printf("Returned value %d - ", (int)retval);
}
pthread_exit(NULL);
}
Output:
Hello from thread 0, pthread ID - 140716669929216
Hello from thread 1, pthread ID - 140716661536512
Hello from thread 2, pthread ID - 140716653143808
Hello from thread 3, pthread ID - 140716644751104
Hello from thread 5, pthread ID - 140716627965696
Hello from thread 4, pthread ID - 140716636358400
Hello from thread 6, pthread ID - 140716550387456
Hello from thread 7, pthread ID - 140716541994752
Use the pthread_join
Function Return Value to Check for Errors
The pthread_join
function returns an integer value that also indicates different error codes in contrast to a function that sets an errno
global variable. The return value is 0
if the call was successful and this guarantees the given thread has terminated. If the returned integer is equal to EDEADLK
, it reports that a deadlock was detected. If EINVAL
value is returned, then the given thread is not joinable, and if the value equals ESRCH
, it indicates that the given thread ID can’t be found. In this case, we implement a switch
statement to check for each case and print the corresponding message to stdout
.
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 8
#endif
void *printHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello from thread %ld, pthread ID - %lu\n", tid, pthread_self());
return NULL;
}
int main(int argc, char const *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t = 0; t < NUM_THREADS; t++) {
rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
if (rc) {
printf("ERORR; return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
int ret;
for (t = 0; t < NUM_THREADS; t++) {
void *retval;
ret = pthread_join(threads[t], &retval);
if (retval == PTHREAD_CANCELED)
printf("The thread was canceled - ");
else
printf("Returned value %d - ", (int)retval);
switch (ret) {
case 0:
printf("The thread joined successfully\n");
break;
case EDEADLK:
printf("Deadlock detected\n");
break;
case EINVAL:
printf("The thread is not joinable\n");
break;
case ESRCH:
printf("No thread with given ID is found\n");
break;
default:
printf("Error occurred when joining the thread\n");
}
}
pthread_exit(NULL);
}
Output:
Hello from thread 0, pthread ID - 140082577512192
Hello from thread 1, pthread ID - 140082569119488
Hello from thread 3, pthread ID - 140082552334080
Hello from thread 5, pthread ID - 140082535548672
Hello from thread 6, pthread ID - 140082527155968
Returned value 0 - The thread joined successfully
Hello from thread 4, pthread ID - 140082543941376
Hello from thread 2, pthread ID - 140082560726784
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Hello from thread 7, pthread ID - 140082518763264
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Returned value 0 - The thread joined successfully
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook