I got this code from an advanced Linux programming book. When I try to execute the code under Linux 64bit environment the value of the which_prime
variable gets corrupted (changes to 0) after pthread_join()
function call.
In this example why the value of which_prime
gets corrupted after running pthread_join?
In general can we use the 4th argument passed to pthread_create function safely inside main even if we call other functions like pthread_join()
?
#include <pthread.h>
#include <stdio.h>
/* Compute successive prime numbers (very inefficiently). Return the
Nth prime number, where N is the value pointed to by *ARG. */
void* compute_prime (void* arg)
{
int candidate = 2;
int n = *((int*) arg);
while (1) {
int factor;
int is_prime = 1;
/* Test primality by successive division. */
for (factor = 2; factor < candidate; ++factor)
if (candidate % factor == 0) {
is_prime = 0;
break;
}
/* Is this the prime number we’re looking for? */
if (is_prime) {
if (--n == 0)
/* Return the desired prime number as the thread return value. */
return (void*) candidate;
}
++candidate;
}
return NULL;
}
int main ()
{
pthread_t thread;
int which_prime = 5000;
int prime;
/* Start the computing thread, up to the 5,000th prime number. */
pthread_create (&thread, NULL, &compute_prime, &which_prime);
/* Do some other work here... */
/* Wait for the prime number thread to complete, and get the result. */
pthread_join (thread, (void*) &prime);
/* Print the largest prime it computed. */
printf(“The %dth prime number is %d.\n”, which_prime, prime);
return 0;
}
We've arrived at a point in time where it is no longer safe to convert between an
int
and apointer
. That's because there are 64-bit systems where a pointer is 64-bits, but anint
is only 32-bits.So assuming 32-bit
int
and 64-bit pointer, here's what's happening in your code. The second argument topthread_join
is a pointer-to-a-pointer. In other words, you should be passing the address of a pointer (the address of a 64-bit value). Instead, you are passing the address ofprime
(the address of a 32-bit value). Whenpthread_join
writes the result, it overwriteswhich_prime
, becausewhich_prime
followsprime
in memory.To fix the problem, you need to avoid converting between
int
s and pointers. One way to do that is to avoid using the second parameter ofpthread_join
, as demonstrated by the following code.