SegFault after the call of pthread_join - c

I am new to threads and I have problem using pthread_join.
This is my code :
int create_threads(t_lemin *lem)
{
int i;
pthread_t **threads;
int j;
void *ret;
t_tree *tmp;
j = -1;
printf("starting algo\n");
threads = xmalloc(sizeof(pthread_t));
i = count_leaf(lem->start);
tmp = lem->start;
printf("%d\n", tmp->visited[0]);
while (++j != i)
{
tmp->leaf[j]->thread_nbr = j;
pthread_create(threads[j], NULL, find_way_out, tmp->leaf[j]);
usleep(100);
}
i = -1;
while (++j != i)
(void)pthread_join (*threads[j], &ret);
//printf("%d\n", *((int*)ret));
return (0);
}
One of my thread finished his work and after the second one finish, I have a Segmentation Fault.
My functions find_way_out returns pthread_exit((void*)j); or pthread_exit(0);
where j is a integer pointer.
Do you have an idea where it can comes from ?
Thanks !

The problem is that you should pass a pointer to an actual pthread_t variable as first argument to pthread_create, as a way of emulating pass by reference, pthread_create will then initialize the object.
Since you pass an uninitialized pointer, you will have undefined behavior when pthread_create dereferences the pointer. And you will have it too when you try to dereference the pointer for the pthread_join call.
And it's even worse, since you only allocate space for one single pthread_t object, so you will go way out of bounds of the "array".
And then for the pthread_join loop, you will have j being some small positive number, while i is a negative number, meaning your loop will iterate a lot since it has to iterate until j overflows and becomes negative and then continue looping until j equals -1.
Instead I suggest these changes:
Use a variable-length array for the pthread_t object
Save the "size" of the array in a variable that you don't change
And finally, use for loops instead
Something like
size_t count = count_leaf(lem->start);
pthread_t threads[count];
for (size_t i = 0; i < count; ++i)
pthread_create(&threads[i], ...);
...
for (size_t i = 0; i < count; ++i)
pthread_join(threads[i], NULL);

Related

How do I get the return value of a function, ran by a pthread?

I have a problem with my C-program and I think I need some help.
My program is doing some calculations using multiple threads. Every thread runs a method with only one parameter and in the end returns an integer.
Now, to complete my calculation, it is necessary to take the sum of all sub-calculations, that means the sum of all integers returned by the threads.
But somehow, that result is not correct. I think I made a mistake in getting all returned integers from the threads.
Here is my code:
//creating the threads (with splitArray[] as an array of pointers to other arrays)
pthread_t threads[n];
for (int i = 0; i < n; i++) {
pthread_create(&threads[i], NULL, (void * )(countPrime), (void * )splitArray[i]);
}
//getting the results of the threads
int numPrimes = 0;
int save;
for (int i = 0; i < n; i++) {
pthread_join(threads[i],(void **) &save);
numPrimes = numPrimes + save;
}
This is the method every given to every thread:
int countPrime(int array[]) {
int numPrimes = 0;
for (int i = 0; i < size; i++) {
//checking if array[i] is a prime number
if (isPrime(array[i])) {
numPrimes++;
}
}
return numPrimes;
}
Have I made a mistake? I am new to C and so I am not really confident about working with pointers, which seems to be necessary in this case.
Thanks a lot :)
The thread function is supposed to be returning a void * pointer, and on a 64-bit machine void * is typically 64 bits wide, while int is typically only 32 bits wide.
When you return a 32-bit value from a function that is expected to return a 64-bit value, what will the extra 32 bits have for value? That's unknown and your code exhibits undefined behavior because of this.
To solve your problem (as I think it might be) you need to update the thread function to return the correct type (void *) and do some casting to make sure the value you return is of the correct type and size:
void *countPrime(int array[]) {
...
return (void *) (intptr_t) numPrimes;
}
Then when you fetch the value, you need to use the correct types as well, and use the opposite casting:
void *result;
for (int i = 0; i < n; i++) {
pthread_join(threads[i],&result);
numPrimes = numPrimes + (int) (intptr_t) result;
}
Note that returning a non-pointer value like this (as well as passing a non-pointer value as argument to the thread function) is almost the only case where most people would agree that such casting is okay. Otherwise, it generally never is.

How to Store Multiple Arrays Returned From Pthread in Another Array Using Pointers

I'm working on a project that needs to run multiple threads concurrently. Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example, in the function that the threads run, the values I want are stored as such:
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
while(condition) {
.
.
.
ptr[0] += x;
ptr[1] += y;
ptr[2] += z;
}
return (void *) ptr;
}
By the end of this function, ptr[0], ptr[1], and ptr[2] hold the desired values. This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
I am required to use pthread_join() to get the various values from each thread. Each thread handles one file, so # of files == # of threads == # of times the above function runs.
I need to take the values of ptr[0], ptr[1], and ptr[2] from each thread and add them together once they are returned to main. Meaning if there are three threads, then I need to add ptr[0] from thread 1 to ptr[0] from thread 2 and ptr[0] from thread 3. The same thing goes for ptr[1] and ptr[2]. Then I need to print the three total values in main at the end. So far this is how I've done it and I got my code to compile but the values are garbage.
int main(int argc, char *argv[]) {
int NUM_THREADS = argc - 1;
int total1 = total2 = total3 = 0;
pthread_t *tids; /* Dynamically allocated array of pthreads */
void **vals; /* Stores the return values from each thread, this could be incorrect */
/*
** Some code where I allocate the arrays etc
*/
for (i= 0; i < NUM_THREADS; i++)
pthread_create(&tids[i], NULL, func, NULL);
for (i= 0; i < NUM_THREADS; i++)
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
for (i= 0; i < NUM_THREADS; i++) {
total1 += ((int*) vals[i])[0]; /* These statements very well could also be wrong */
total2 += ((int*) vals[i])[1];
total3 += ((int*) vals[i])[2];
}
/* Print totals */
return 0;
}
I know the values in each thread are correct at the end of func, but I don't know how to properly store, process, and print them in main.
Also, I am using C90 and cannot use any functionality from any other version of C and I must store the values using pthread_join().
Each thread runs a function that returns a pointer to an array of ints (cast as a void pointer). For example
void *func(void *args) {
int vals[3] = {0, 0, 0}, x = y = z = 0;
int *ptr = vals;
...
return (void *) ptr;
}
You should start by fixing the function to return something meaningful. As currently written, the function returns a pointer to automatic array vals, which no longer exists after the function returns.
Any use of the returned pointer will produce undefined behavior.
This code is just to give you an idea of whats happening, there is nothing wrong with my actual implementation.
It's somewhat hard to believe that.
pthread_join(tids[i], &(vals[i])); /* Again, this could be wrong */
That is wrong: vals is uninitialized at this point, so you are writing all over random memory.
I don't know how to properly store, process, and print them in main.
Here is how:
void *vals[NUM_THREADS];
..
for (i= 0; i < NUM_THREADS; i++) {
pthread_join(tids[i], &vals[i]);
}
for (i= 0; i < NUM_THREADS; i++) {
int *p = (int *)vals[i];
total1 += p[0];
total2 += p[1];
... etc.
}

Unexpected results from passing int-value in multithreading, C

I am currently trying to learn about multi-threading in C. But I have got very unexpected results which have left me stumped. In this program, I am trying to fill up a matrix by using threads. I am creating 1024 threads, passing the i value into the function. Then I proceed to use it.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define SIZE 1024
static double a[SIZE][SIZE];
static double b[SIZE][SIZE];
static double c[SIZE][SIZE];
void*
init_matrix(void* msg)
{
int j;
int num = *((int*) msg);
printf("%d\n", num);
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
pthread_exit(NULL);
}
int
main(int argc, char **argv)
{
//Init threads
pthread_t p_initThreads[SIZE];
int i,j;
for(i = 0; i< SIZE; i++)
{
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)&i);
}
for(j = 0; j<SIZE; j++)
{
pthread_join(p_initThreads[j], NULL);
}
}
Expected results from the prinf would be; 1-2-3-4-5-6-7-8-9-10. With the possible
result of it being inorder due to of it being in threads. But the reults on my computer is this;
1-2-2-4-5-7-24-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-25-26-35-36-36-37-37-37-37-37-37-37-37-38-39-40
By commentating out;
for (j = 0; j < SIZE; j++) {
a[num][j] = drand48();
b[num][j] = drand48();
}
I get the result that I want. Why is that? It should not do anything to num!
You are passing the address of i as the input parameter of the thread. If you were passing the value of i, you would get 1-2-3-4-5-... . But when you pass the address, it is entirely possible that before the printf line is executed, the main thread already incremented i. And printf displays the current value of i, not the value it had at the moment of thread creation.
What you have is a race condition with multiple threads accessing the same memory location (variable i) since you are passing the address of i to all threads.
What you really wanted to do was pass the value of i. Call the pthread_create() with:
pthread_create(&p_initThreads[i], NULL, init_matrix, (void*)i);
and read the value as:
int num = (int) msg;
instead of : int num = *((int*) msg);
You should also check if pthread_create() returns non-zero for failures. If that's the case, you are not going to get expected results.

How to save pthread_t id to an array

How can i save the id of p_thread to an array?
int i;
pthread_t t[N];
float arrayId[N];
for (i = 0; i < N; i++) {
pthread_create(&t[i], NULL, f, (void *) &i);
printf("creato il thread id=%lu\n", t[i]);
arrayId[i] = t[i];
printf("a[%d]=%f\n", i, arrayId[i]);
}
I can print it, but i'm not able to save...
I'll have to sort this array and then i'll have to execute first all the thread ordered by id
All threads will receive the same value for i because you are passing it by value (the same address).
This should fix it:
int i;
pthread_t t[N];
float arrayId[N];
int indexes[N];
for (i = 0; i < N; i++) {
indexes[i] = i;
pthread_create(&t[i], NULL, f, (void *) &indexes[i]);
printf("creato il thread id=%lu\n", t[i]);
arrayId[i] = t[i];
printf("a[%d]=%f\n", i, arrayId[i]);
}
I'll have to sort this array and then i'll have to execute first all the thread
ordered by id
pthread_create already executes a thread as man states:
The pthread_create() function starts a new thread in the calling process.
So your loop already starts N threads. Also you can't specify thread ids, they are returned when threads are created.
You don't need to save the array. You simply define a function, f, that you wish to operate on these numbers, and then, as you have done in your pthread_create(), have that function, f, as an input.
Each time pthread_create() is called the function, f, will be executed.

How can I initiate an array, each element in a separate thread

I am trying to create an array of size n (where n is user's input) and when the user runs the program, the array elements should be set to 1 (each in a separate thread). Here is what I have done so far:
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>
int *x;
DWORD WINAPI init_X(LPVOID param)
{
int index = *(int *) param;
x[index] = 1;
return 0;
}
int main(int argc, char *argv[])
{
int n = atoi(argv[1]);
int i; // counter.
HANDLE THandles[n];
x = malloc(n * sizeof (int));
for(i = 0; i < n; i++)
{
THandles[i] = CreateThread(NULL, 0, init_X, &i, 0, NULL);
}
// Now wait for threads to finish
WaitForMultipleObjects(n, THandles, TRUE, INFINITE);
// Close the thread handle
for(i = 0; i < n; i++)
{
CloseHandle(THandles[i]);
}
printf("After initialization x = ");
for(i = 0; i < n; i++)
{
printf("%d ", x[i]);
if(i < n - 1) printf(" ");
}
// ...
return 0;
}
I run this program and I got wrong outputs:
> Test.exe 3
After initialization x = 11611536 11600064 50397186
It should be After initialization x = 1 1 1 though. I am not sure how I can I fix this, but I am sure its something related to the pointers.
P.S: I'm Java programmer so I'm not familiar with pointers.
The value you are passing as your array index will more than likely be invalid by the time the thread runs, as there is no guaranteeing that the thread is run immediately after the call to CreateThread.
You have two solutions, either pass by value (simple & easy, but not always safe) or allocate a temporary buffer for the value that will be freed by the thread when its used.
Minor Update:
In fact, a better way would be to pass &x[i], then you can just do *(int*)param = 1;
You are passing i by pointer to the thread, so the value each thread gets will depend on when int index = *(int *) param; actually executes and it should be something between 0 and n. You can just pass i by value (casted to a pointer) to avoid this.

Resources