Reputation: 332
I am trying to get a grasp on the use of POSIX threads and created a simple program that simply increments a global variable by 10. On sometimes it runs all the way through fine, other it seg faults in random spots. While this type of issue seems to be a regular thing with threads, I cannot understand why this happens in such a simple example. My current thought is maybe the parent is ending before due to not joining the threads, but if i try to join i seg fault on first thread... The Join statement is left in but commented out. Is Join used in correct syntax? Is not preforming the join leading to the seg fault?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define NUMPHILO 5
thread_t threads[NUMPHILO]; //array of threads
pthread_mutex_t mutex; // initialize mutex
int x = 5; //for test
int y = 10;
int philofunct(){
pthread_mutex_lock (&mutex);
x = x+y;
pthread_mutex_unlock (&mutex);
printf("Philo fucntion x = %d\n",x);
return x;
}
int main(){
pthread_mutex_init(&mutex, NULL);
for(int i = 0; i < NUMPHILO; i++){
printf("creating thread[%i]\n",i);
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
fprintf(stderr, "%s", strerror(errno));
// pthread_join(threads[i],NULL);
// printf("Threads Joined\n");
}
pthread_mutex_destroy(&mutex);
printf("Threads created\n");
}
output:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
creating thread[3]
Philo fucntion x = 45
creating thread[4]
Philo fucntion x = 55
Threads created
next time ran:
creating thread[0]
Philo fucntion x = 15
creating thread[1]
Philo fucntion x = 25
creating thread[2]
Philo fucntion x = 35
Segmentation fault (core dumped)
As always, any help is greatly appreciated.
Upvotes: 1
Views: 62
Reputation: 34829
The main thread is destroying the mutex before the child threads are finished with it. pthread_join
will solve the problem, but the pthread_join
needs to be in a separate loop after all of the threads have been created.
for(int i = 0; i < NUMPHILO; i++)
pthread_join(threads[i],NULL);
The function signature for the philofunct
is wrong. In general, if you need a cast, you're doing something wrong. (Yes, there are some cases where a cast is necessary and useful. This is not one of those cases.) The correct signature is
void *philofunct( void *arg );
and the correct call to pthread_create
is
if( pthread_create(&threads[i], NULL, philofunct, NULL) != 0)
Note that passing the address of i
won't do what you want, but that's a separate question, and you haven't gotten to that point yet.
Upvotes: 1
Reputation: 4767
The main problem you have is here:
if( pthread_create(&threads[i], NULL, (void *)philofunct(),(void *) &i) != 0)
Look carefully, you are calling philofunct()
instead of passing the function pointer to it. Worse, you are passing the return value of philofunct()
, which is some integer such as 15
, as the function pointer to pthread_create()
. Naturally, the thread will segv when it tries to execute code from an address such as 15
.
Once you define philofunct()
correctly like this:
void *philofunct(void *arg)
You can then call pthread_create()
without a cast:
if( pthread_create(&threads[i], NULL, philofunct,(void *) &i) != 0)
Also, if you want to join your threads, you should join your threads after they are all running. If you join the thread in the creation loop, you will be waiting for each thread to finish before creating the next one. So you would write it like this:
for (i=0;i<NUMPHILO; i++) {
pthread_create(&threads[i], ...);
// Other stuff...
}
for (i=0;i<NUMPHILO; i++)
pthread_join(threads[i], NULL);
Upvotes: 4
Reputation: 16056
I see several problems with your code before even considering what you want:
x
outside of the section locked by the mutex.pthread_join
them all. Alternatively, you could pthread_exit
the main thread instead of letting main
terminate (and never destroy the mutex, which is not a leak since there's only one of them and its lifetime ends with the lifetime of the program), but killing the main thread sometimes makes funny kernel "bugs" happen.Upvotes: 4