pthread_join corrupts pthread_create argument in the stack - c

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 a pointer. That's because there are 64-bit systems where a pointer is 64-bits, but an int is only 32-bits.
So assuming 32-bit int and 64-bit pointer, here's what's happening in your code. The second argument to pthread_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 of prime (the address of a 32-bit value). When pthread_join writes the result, it overwrites which_prime, because which_prime follows prime in memory.
To fix the problem, you need to avoid converting between ints and pointers. One way to do that is to avoid using the second parameter of pthread_join, as demonstrated by the following code.
#include <stdio.h>
#include <pthread.h>
#define NUM_THREADS 20
typedef struct
{
int success;
int input;
int output;
} stData;
void *doSomething( void *arg )
{
stData *dataptr = arg;
dataptr->success = 1;
dataptr->output = dataptr->input * 2;
return NULL;
}
int main( void )
{
int i;
pthread_t id[NUM_THREADS];
stData data[NUM_THREADS] = {{0}};
for ( i = 0; i < NUM_THREADS; i++ )
{
data[i].input = i + 1;
pthread_create( &id[i], NULL, doSomething, &data[i] );
}
for ( i = 0; i < NUM_THREADS; i++ )
{
pthread_join( id[i], NULL );
if ( data[i].success )
printf( "thread %2d: input=%2d output=%2d\n", i+1, data[i].input, data[i].output );
else
printf( "thread %2d: failed\n", i+1 );
}
return 0;
}

Related

Multiple threads to find prime factors of integers, segmentation fault

I can't figure out what I am doing wrong with my pointers. It is causing a segmentation fault. I am convinced the problem is rooted in my use of the array of pointers I have and the pthread_join I am using.
The goal is to read multiple integers into a gcc compiler, then print out the integer with all its factors, like this, 12: 2 2 3
I created a struct containing an int array to store the factors of each integer as the factor function pulls it apart and a counter(numfact) to store how many factors there are stored in the array.
I commented out the section at the bottom that prints out the factors.
I think the problem is how I am trying to store the output from the pthread_join in the pointer array, ptr[]. Whenever I comment it out, it does not get the segmentation error.
Either I have my pointers screwed up in a way I don't understand or I can't use an array of pointers. Either way, after many hours, I am stuck.
Please help.
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <stdlib.h>
struct intfact
{
long int factors[100];
int numfact;
};
struct intfact *factor(long int y)
{
struct intfact threadfact;
threadfact.numfact = 0;
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
threadfact.factors[threadfact.numfact] = 2;
threadfact.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
threadfact.factors[threadfact.numfact] = i;
threadfact.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
threadfact.factors[threadfact.numfact] = y;
threadfact.numfact++;
}
struct intfact *rtnthred = &threadfact;
return rtnthred;
}
/* Trial Division Function */
void *divde(void *n)
{
long int *num = (long int *) n;
struct intfact *temp = factor(*num);
return temp;
}
/* Main Function */
int main(int argc, char *argv[])
{
pthread_t threads[argc-1];
void *ptr[argc-1];
/* loop to create all threads */
for(int i=0; i < argc; i++)
{
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
}
/* loop to join all threads */
for(int i=0; i < argc; i++)
{
pthread_join(threads[i],(void *) ptr[i]); //THIS POINTER IS THE PROBLEM
}
/* loops to print results of each thread using pointer array*/
//for(int i = 0; i < argc; i++)
//{
// printf("%s: ", argv[i+1]); /* print out initial integer */
// struct intfact *temp = (struct intfact *) ptr[i]; //cast void pointer ptr as struct intfact pointer
// printf("%d", temp->numfact);
//for(int j = 0; j < temp->numfact; j++) /*(pull the numfact(count of factors) from the struct intfact pointer??)*/
//{
// printf("%d ", temp->factors[j]); /* print out each factor from thread struct */
//}
}
}
In my Linux) terminal this code is stored in p3.c
"./p3 12" should yeild "12: 2 2 3"
For starters:
Here
long temp = atol(argv[i+1]);
pthread_create(&threads[i], NULL, divde, (void *) temp);
you define a long int and pass it as argument to the thread. For example 12
Inside the thread function then
void *divde(void *n)
{
long int *num = (long int *) n;
you treat the long int passed in as pointer to long int.
And then here dereference it
... = factor(*num);
So this *num for example would become *12. That is referencing memory address 12 to read out its content and pass it to factor). Aside the fact that this mostly likely is an invalid address, there would be nothing relevant store, at least nothing your code defined.
To (more or less fix) this do
void *divde(void *n)
{
long int num = (long int) n;
... = factor(num);
The second issues is mentioned in the comment: Multiple threads to find prime factors of integers, segmentation fault
The problem you are trying to solve is a special case of parallel programming, namely that the tasks to be run in parallel are completely independent. In such cases it makes sense to give each task its own context. Here such a context would include the
thread-id,
the thread specific input
as well as its specific output.
In C grouping variables can be done using structures, as your implementation already comes up with for the output of the tasks:
struct intfact
{
long int factors[100];
int numfact;
};
So what is missing is thread-id and input. Just add those for example like this.
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
Now before kicking off the threads define as many contexts as needed:
int main(int argc, char *argv[])
{
size_t num_to_process = argv - 1;
struct context ctx[num_to_process];
then create the threads passing in what is needed, that is input along with space/memory for the output:
for (size_t i = 0; i < num_to_process ; i++)
{
ctx[i].io.input = atol(argv[i]);
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
Inside the thread function convert the void-pointer received back to its real type:
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
Define the processing function to take a pointer to the context specific input/output variables:
void factor(struct inout * pio) /* No need to return any thing */
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pio->input directly. */
Replace all other occurrences of threadfact by pio->output.
Use
return;
}
to leave the processing function.
Then inside the thread function call the processing function:
factor(pio);
Use
return NULL;
}
to leave the thread function.
In main() join without expecting any result from the threads:
/* loop to join all threads */
for (size_t i = 0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
Putting this all together:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
struct intfact
{
long int factors[100];
size_t numfact;
};
/* group input and output: */
struct inout
{
long int input;
struct intfact output;
};
/* group input/output with thread-id */
struct context
{
pthread_t thread_id;
struct inout io;
};
void factor(struct inout * pio)
{
/* Initialise the output: */
pio->output.numfact = 0;
/* set local copy of input: */
long int y = pio->input; /* One could also just use pinout->input directly. */
if (0 == y)
{
return; /* Nothing to do! */
}
// Store in struct the number of 2s that divide y
while (y % 2 == 0)
{
pio->output.factors[pio->output.numfact] = 2;
pio->output.numfact++;
y = y/2;
}
// Store in struct the odds that divide y
for (int i = 3; i <= floor(sqrt(y)); i = i+2)
{
while (y % i == 0)
{
pio->output.factors[pio->output.numfact] = i;
pio->output.numfact++;
y = y/i;
}
}
// Store in struct the primes > 2
if (y > 2)
{
pio->output.factors[pio->output.numfact] = y;
pio->output.numfact++;
}
return;
}
void *divide(void * pv)
{
struct inout * pio = pv; /* No cast needed in C. */
factor(pio);
return NULL;
}
int main(int argc, char *argv[])
{
size_t num_to_process = argc - 1;
struct context ctx[num_to_process];
for (size_t i = 0; i < num_to_process; i++)
{
ctx[i].io.input = atol(argv[i+1]);
if (!ctx[i].io.input)
{
fprintf(stderr, "COnversion to integer failed or 0 for '%s'\n", argv[i]);
}
pthread_create(&ctx[i].thread_id, NULL, divide, &ctx[i].io);
}
/* loop to join all threads */
for (size_t i=0; i < num_to_process; i++)
{
pthread_join(ctx[i].thread_id, NULL);
}
/* loops to print results of each thread using pointer array*/
for(size_t i = 0; i < num_to_process; i++)
{
printf("%ld: ", ctx[i].io.input); /* print out initial integer */
printf("%zu factors --> ", ctx[i].io.output.numfact);
for(size_t j = 0; j < ctx[i].io.output.numfact; j++)
{
printf("%ld ", ctx[i].io.output.factors[j]); /* print out each factor from thread struct */
}
putc('\n', stdout);
}
}

Trying to pass integer argument to thread

Hi I am having trouble passing an integer argument to a thread and calculation the factorial using that integer. Here is my code.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ctype.h>
void * factorial(void * number) {
int factorial = 1;
int counter = 1;
int newnum = *((int*)number);
printf("%d", newnum);
pthread_exit(NULL);
}
void * sumup( void * number) {
}
int main(int argc, char *argv[]) {
if(argc != 2) {
printf("Argument number error\n");
exit(1);
}
pthread_t thread1;
pthread_t thread2;
int i;
for(i = 0; i < argc; i++){
printf(argv[i]);
printf("\n");
}
int rc;
void * t = argv[1];
rc = pthread_create(&thread1, NULL, factorial, (void*)t );
if (rc != 0) {
printf("There was an error creating the thread\n");
exit(1);
}
pthread_exit(NULL);
exit(0);
}
Right now i am just trying to print the integer sent to get it working properly but here is my output:
./Task1
5
1162608693
It should printing out 5 instead of 1162608693
argv table stores pointers to characters. By doing:
void * t = argv[1];
int newnum = *((int*) t );
what you are trying to print is integer value of string "5". You are passing address of string:
'5' '\0'
casted to pointer to int, therefore you try to read integer value of first sizeof(int) bytes which yields:
5 0 [and you read sizeof(int)-2 bytes out of range]
which results in undefined behavior.
SOLUTION
To convert to integer a string passed as argument to your program use atoi or strtol which does better error checking.

Multithreading in c using a thread safe random numbers

I have been trying to get this to pass valgrind leak check and also pass in 2 billion random numbers and divide them between the threads. I keep getting a seg fault once I get to 1 billion random numbers. Where am I allocating wrong or what am I doing wrong?
struct thread
{
long long int threadID; //The thread id
long long int operations; //The number of threads
};
void *generateThreads(void *ptr)
{
struct thread *args = ptr;
struct random_data *rdata = (struct random_data *) calloc(args->operations*64,sizeof(struct random_data));
char *statebuf = (char*) calloc(args->operations*64,BUFSIZE);
long long int i;
int32_t value;
for(i = 0; i < args->operations; i++)
{
initstate_r(args->threadID,&statebuf[i],BUFSIZE,&rdata[i]);
random_r(rdata,&value);
}
if(DEBUG > 1)
printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());
free(rdata);
free(statebuf);
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
long long int numRandoms;
long long int numThreads;
double timeStart = 0;
double timeElapsed = 0;
pthread_t *tid;
struct thread args;
if (argc != 3)
{
fprintf(stderr, "Usage: %s <Number of Randoms> <Number of Threads>\n" ,argv[0]);
exit(1);
}
/* Assign the arg values to appropriate variables */
sscanf(argv[1],"%lld",&numRandoms); /* lld for long long int */
sscanf(argv[2],"%lld",&numThreads); /* lld for long long int */
/* Number of threads must be less than or equal to the number of random numbers */
if(numRandoms < numThreads)
{
fprintf(stderr,"Number of threads must be less than or equal to the number of random numers.\n");
exit(1);
}
/*Start*/
long long int i;
args.operations = numRandoms/numThreads;
timeStart = getMilliSeconds();
tid = (pthread_t *) calloc(numThreads,sizeof(pthread_t));
/* value is the thread id, creating threads */
for(i = 0; i < numThreads; i++)
{
args.threadID = i;
pthread_create(&tid[i],NULL,generateThreads,(void *) &args);
}
/* Joining the threads */
for(i = 0; i < numThreads; i++)
{
pthread_join(tid[i],NULL);
}
/*Output*/
timeElapsed = getMilliSeconds() - timeStart;
printf("%lf\n",(double)(timeElapsed/1000.0));
free(tid);
fflush(stdout);
exit(0);
}
OK I figured out what you were trying to do. The problem was that whatever code you copied from used initstate_r in main to set up the states for all threads. It called initstate_r once per thread to set up the rng for that thread. But you copied that loop into each thread, so you were calling initstate_r many times per thread which is useless. The *64 was there originally to make each state occupy 64 bytes in order to keep them on separate cache lines. You probably were referring to this stackoverflow question.
Here is your function rewritten to make much more sense:
void *generateThreads(void *ptr)
{
struct thread *args = ptr;
struct random_data *rdata = calloc(1,sizeof(struct random_data));
char statebuf[BUFSIZE];
long long int i;
int32_t value;
initstate_r((int) pthread_self(),statebuf,BUFSIZE,rdata);
for(i = 0; i < args->operations; i++)
{
random_r(rdata,&value);
if(DEBUG > 1)
printf("%d\n", value);
}
if(DEBUG > 1)
printf("I am thread %lld with thread id %X\n", args->threadID, (unsigned int) pthread_self());
free(rdata);
pthread_exit(NULL);
}
By the way, the way you pass your arguments to your threads is wrong. You pass the same args to each thread, which means they are sharing the same args structure, which means they each share the same args->threadID. You should instead pass each thread its own args structure.
My answer to question link provides thread safe pseudo-random number generator designed for __uint64/__uint128 integers using xorshift algorithm.
Additional properties:
shared-reentrant
lock-free
thread-safe
ultrafast
seeded from two variant sources of enthropy

Passing information to multiple threads in the dining philosopher's algorithm

I am trying to create multiple threads and pass a different value to each thread for the dining philosopher's problem. But I am getting this error:
warning: cast to pointer from integer of different size
Here is my code:
pthread_mutex_t mutex;
pthread_cond_t cond_var;
pthread_t philo[NUM];
int main( void )
{
int i;
pthread_mutex_init (&mutex, NULL);
pthread_cond_init (&cond_var, NULL);
//Create a thread for each philosopher
for (i = 0; i < NUM; i++)
pthread_create (&philo[i], NULL,(void *)philosopher,(void *)i); // <-- error here
//Wait for the threads to exit
for (i = 0; i < NUM; i++)
pthread_join (philo[i], NULL);
return 0;
}
void *philosopher (void *num)
{
//some code
}
The warning is simply means that an int is not necessarily the same size as a pointer on all platforms. To avoid the warning, you could declare i as an intptr_t. An intptr_t is guaranteed to be the same size as a pointer. But allow me to suggest an alternative solution.
The code below demonstrates how to start multiple threads while passing a unique piece of information to each thread. The steps are
declare an array that has one entry for each thread
initialize the array entry for each thread
pass the array entry to the thread
retrieve the information from the array when the thread starts
In sample code below, we want to pass a single integer to each of the threads, so the array is just an array of int. If more information is needed per thread, it would be appropriate to have an array of structs.
The code starts five threads. Each thread is passed a unique ID (an int between 0 and 4) which it prints to the console after a short delay. The purpose of the delay is to demonstrate that the threads will each get a unique ID, regardless of when they start.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#define NUM 5
static int infoArray[NUM]; // 1. declare an array with one entry for each thread
void *philosopher( void *arg );
int main( void )
{
int i;
pthread_t threadID[NUM];
srand( time(NULL) );
for ( i = 0; i < NUM; i++ )
{
infoArray[i] = i; // 2. initialize the array entry for this thread
// 3. pass the array entry to the thread
if ( pthread_create( &threadID[i], NULL, philosopher, (void *)&infoArray[i] ) != 0 )
{
printf( "Bad pthread_create\n" );
exit( 1 );
}
}
for ( i = 0; i < NUM; i++ )
pthread_join( threadID[i], NULL );
return( 0 );
}
void *philosopher( void *arg )
{
sleep( rand() % 3 );
int id = *(int *)arg; // 4. retrieve the information from the array
printf( "%d\n", id );
return( NULL );
}

Threads receiving the same ID in C

Here is a block of code that creates a number of threads provided by the user, each thread then generates a random number and calculates its squareroot. I cannot figure out why the threads are getting the same ID, line 64 is the culprit as it is where the threads are being created. I suspect that there is something happening in the loop that is causing the threads to all be generated at the same time.
////////////////////////////////////////////////
//
//
// Zach
//
//
//
//
////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
void *squareroot(void *num1)
{
int *id = (int *)num1;
int incoming = rand()/100;
float *outgoing = (float *)malloc(sizeof(float));
printf("%d \n", *id);
printf("%d\n", incoming);
*outgoing = 5.000;
//Calculate the square root of the number passed to the function
*outgoing = sqrt(incoming);
return outgoing;
}
int main(int argc, char* argv[])//testing funcion
{
srand(time(NULL));
int i, j;
int *temp = (int *)malloc(sizeof(int));
if (argc != 2)
{
printf ("ERROR: Enter a number\n");
return 1;
}
int loop = atoi(argv[1]); //grabbing the integer supplied by user
pthread_t thread_id[loop];
void *exit_status;
float *thread_result;
for(i = 0; i < loop; i++)
{
pthread_create(&thread_id[i], NULL, squareroot, &i);
}
for(j = 0; j < loop; j++)
{
pthread_join(thread_id[j], &exit_status);
thread_result = (float *)exit_status;
printf("%f\n", *thread_result);
}
}
I think what is happening is that your loop finishes creating all the threads (or at least some of them) before any of the threads actually run and extract their unique id.
Because you're passing a pointer to i, when each thread finally gets around to checking its parameter, i is already finished... Or at least partway through. The danger is that multiple threads might see the same value for i. It's even worse that you never copy the value out of that pointer - you always dereference it. That means it might change in the middle of your thread's execution.
What you should do instead is pretend it is a pointer:
pthread_create(&thread_id[i], NULL, squareroot, (void*)i);
And in your thread function:
int id = (int)num1;
This works because the pointer is passed by value. Whatever value you provide is the value that goes into the thread function. Previously it didn't work because you passed a pointer to a value that could change in another thread.
PS: Don't forget to free the result from each thread in your loop at the end. At the moment you're not cleaning up memory that you allocated.

Resources