Segfault at pthread_join (only sometimes) - c

I want to use a bunch of pthreads in my application. To get familiar with the pthread library, I started with a small demo application (see attached sourcecode).
If I create 200 threads, all works well. However, if I increase the number of threads to 2000 the application crashes with a segfault. According to gdb the segfault happens at pthread_join. Unfortunately I could'nt figure out why this is happening.
First, I thought, that my linux machine could'nt handle that many threads, so I increased the value in /proc/sys/kernel/threads-max, but that didn't change anything.
What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define THREADS 200 //If I increase this value to 2000, the application crashes with a segfault
struct tInfo_t{
int sockfd;
};
pthread_t workerThreads[THREADS];
struct tInfo_t tInfo[THREADS];
void *handle(void *arg){
struct tInfo_t threadArgs = *((struct tInfo_t*)arg);
pthread_exit(0); //do nothing, just exit
return NULL; //to make the compiler happy
}
int main(int argc, char *argv[])
{
int i = 0;
//create a few threads
for(i = 0; i < THREADS; i++){
if(pthread_create(&workerThreads[i], 0, handle, (void*)&tInfo[i]) == -1){
printf("couldn't create thread. %d \n", workerThreads[i]);
return EXIT_FAILURE;
}
printf("Thread #%d spawned\n", i);
}
//wait until all threads finished their job
for(i = 0; i < THREADS; i++){
pthread_join(workerThreads[j], NULL);
}
return EXIT_SUCCESS;
}

Related

How to detect starvation in reader-writer problem

I have a question about this piece of code I have. It is the classic readers-writers problem. I followed the pseudo-code found on this wikipedia page for the first problem that has writers starving. I would like to know how I would actually notice the starvation of the writers going on.
I tried putting print statements of the shared_variable in various places, but this didn't give me much insight. But maybe I just didn't understand what was going on. Would someone be able to explain to me how I could visually see the starvation happening? Thank you!
The number of attempts that the reader or writer would attempt to read or write is given as a command line argument.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
// Compile it like so: gcc assignment2.c -lpthread
// Shared variables (semaphore and integer)
static sem_t rw_mutex;
static sem_t mutex;
static int read_count = 0;
// Shared variable
int shared_variable = 0;
static void *writerAction(void *arg){
int number_attempt = *((int *) arg);
int attempt = 0;
do{
sem_wait(&rw_mutex);
shared_variable = shared_variable + 10;
sem_post(&rw_mutex);
attempt++;
}while(attempt < number_attempt);
}
static void *readerAction(void *arg){
int number_attempt = *((int *) arg);
int attempt = 0;
do{
sem_wait(&mutex);
read_count++;
// waiting to be able to read for the possible writer
if (read_count == 1 ){
sem_wait(&rw_mutex); // get the lock so that writter can't write!
}
// Release the read_count variable
sem_post(&mutex);
sem_wait(&mutex);
read_count--;
if (read_count == 0){
sem_post(&rw_mutex); // release the lock so that writter can write
}
sem_post(&mutex);
attempt++;
} while(attempt < number_attempt);
}
int main(int argc, char *argv[]) {
int number_writers = 10;
int number_readers = 500;
int reader_repeat_count = atoi(argv[2]);
int writer_repeat_count = atoi(argv[1]);
// Instantiating the threads for the writters and readers
pthread_t writer_threads[number_writers];
pthread_t reader_threads[number_readers];
// Initation of semaphores
sem_init(&rw_mutex, 0, 1);
sem_init(&mutex, 0, 1);
printf("Start creation of Readers\n");
for(int i = 0; i <number_readers; i++){
pthread_create(&reader_threads[i], NULL, readerAction, &reader_repeat_count);
}
printf("Start creation of Writers\n");
for(int i = 0; i < number_writers; i++){
pthread_create(&writer_threads[i], NULL, writerAction, &writer_repeat_count);
}
// All the actions is hapenning here
printf("Wait for Readers\n");
for(int i = 0; i < number_readers; i++){
printf("Waiting for : %d\n",i);
pthread_join(reader_threads[i], NULL);
}
printf("Wait for Writers\n");
// Collect all the writers
for(int i = 0; i < number_writers; i++){
printf("Waiting for : %d\n",i);
pthread_join(writer_threads[i], NULL);
}
// Results
printf("The shared variable is : %d\n",shared_variable);
}
First of all there is a syntax error, the return type of writerAction and readerAction should be void not void*
In order to see writer starvation you can print "writer trying to write" just before writer is trying to acquire the rw_mutex, the call to sem_wait(&rw_mutex). Add another print when the writer has updated the shared variable, inside the critical section. Add one more printf just after the the entry section of the reader. Which is this code.
// Release the read_count variable
sem_post(&mutex);
printf("reader reading shared value %d\n", shared_variable);
Now when you run the code with large repeat count, You will see "writer trying to write" then you will see a large number of reader printouts instead of the one from writer updating the shared variables, which will prove that the readers are starving the writer by not allowing it to update the variable.

POSIX pthread_join hangs after thousands of threads

I am new to POSIX and I cant find a solution to this particular problem.
Are there any known issues with creating pthreads inside of loop with big number of iterations(>100000)?
It seems like every time I execute, it hangs on a random pthread_join.
I've tested for memory leaks and thread stack usage with valgrind.
If I interrupt gdb when the program hangs it will trace the problem to pthread_join.
This is example code recreates my problem.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* task(void* args);
int main(int argc, char **argv)
{
int num_threads = 4;
int m = 100000;
int i;
for(i = 0; i < m; i++)
{
fprintf(stdout, "i:%d\n",i);
//parallel region starts
pthread_t threads[num_threads];
int t,rc;
for(t = 0; t < num_threads; t++)
{
rc = pthread_create(&threads[t],NULL,task,NULL);
if(rc){
fprintf(stderr,"ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for(t = 0; t < num_threads; t++)
{
rc = pthread_join(threads[t],NULL);
if(rc){
fprintf(stderr,"ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
//parallel region ends
}
pthread_exit(NULL);
}
//thread task
void* task(void* args)
{
pthread_exit(NULL);
}
Verified your code on an Ubuntu machine i7-4600U CPU # 2.10GHz
I don't see any issue with your code, just to verify i compiled and run your code on my local machine it seems to work fine.
i got the output as expected:
i:999,j:999
so I am assuming the issue you you are experiancing has something to do with your environment. what CPU OS and GCC are you using?

Multithreaded semaphore program

I've spent quite a few hours on trying to figure this one out and I'm completly stuck. The program is supposed to start 6 threads. Where some threads start where others end. Right now, I'm trying to get one single thread (thread 0) to execute. The caps lock commenting shows where I have added code and done my mistakes. My main struggle here is dealing with the pointers. Could anyone give me any pointers (ha..ha.. :c )?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define SHARED 1
sem_t sem[6];
struct threadargs
{
int id; /* thread number */
int sec; /* how many sec to sleep */
int signal[6]; /* which threads to signal when done */
};
void *tfunc(void *arg)
{
int i;
struct threadargs *targs=arg;
sem_wait(sem); //WAIT FOR OWN SEMAPHORE
printf("Thread %d is running\n", targs->id);
sleep(targs->sec);
printf("Thread %d is completed and may wake others..\n", targs->id);
for(i=0; i<6; i++) //ITERATE OVER signal_ARRAY &
{ //WAKE THREAD NUMBER i IF
if(targs->signal[i] == 1) //signal[i] IS 1
pthread_cond_signal(&sem[i]);
}
}
int main(void)
{
int i, j;
struct threadargs *targs[6];
pthread_t tid[6];
for(i=0; i<6; i++)
{
targs[i] = (struct threadargs*) malloc(sizeof(struct threadargs));
for(j=0; j<6; j++)
{ targs[i]->signal[j]=0; }
}
targs[0]->id=1;
targs[0]->sec=1;
targs[0]->signal[1]=1;
targs[0]->signal[4]=1;
sem[0] = 0; //INITIALIZE THREAD'S SEMAPHORE TO 0 or 1
pthread_create(targs[0], NULL, tfunc, NULL) // START THREAD
for(i=0; i<6; i++)
pthread_join(tid[i], NULL);
return 0;
}
Alright. First things first, I do recommend taking a second look at your coding style. It is of course highly subjective and I won't say yours is bad, but it took me a while to figure it out (if you really want to know, I recommend the Linux coding style for C/C++ code).
Lets get on with your problem. As far as I can see, the main issue seems that you're basically comparing pointers to apples with pointers to banana's (in other words, you're using the wrong pointer type in the wrong place).
To make sure that calls to functions and the like are correct, make sure to look up the API documentation for functions that are new to you (examples: pthread_create, sem_init, sem_wait, sem_post, pthread_cond_signal).
As you can see, pthread_cond_signal doesn't take a sem_t* as argument, and therefore you can't pass one to it and expect it to work. Below you'll find an example program showing how semaphores are used.
First, a new thread is created which will be put in waiting state instantly. As soon as the main tread finished counting from 0 to 150, it will post ('unlock') the semaphore and allowing the second thread to finish its execution.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
static sem_t sem_thread_one;
static pthread_t thread_one_data;
static int x;
static void *tfunc(void *arg)
{
sem_wait(&sem_thread_one);
printf("Thread 1 is running. The value of x is %i\n", x);
return NULL;
}
int main(int argc, char **argv)
{
sem_init(&sem_thread_one, 0 /* don't share between processes */, 0);
if(pthread_create(&thread_one_data, NULL, &tfunc, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
while(x < 150) {
x++;
}
sem_post(&sem_thread_one);
if(pthread_join(thread_one_data, NULL)) {
fprintf(stderr, "Could not join threads, exiting!\n");
return -EXIT_FAILURE;
}
sem_destroy(&sem_thread_one);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file sem.c and compile & link using:
gcc -Wall -Os -pthread -o sem_test sem.c
Now a second example, but now using pthread_cond_t. The functionality of the program is somewhat similar, it waits for a counter to reach a certain number.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
static pthread_t thread_one_data, thread_two_data;
static volatile int x, y, idx = 10;
static int count = 1;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
static void *cond_test_wait(void *arg)
{
pthread_mutex_lock(&mutex);
while(count < 10) {
printf("Waiting for `count < 10' to become true\n");
pthread_cond_wait(&condition, &mutex);
}
pthread_mutex_unlock(&mutex);
printf("Test wait thread finished. Value of count: %i\n", count);
return NULL;
}
static void *cond_test_signal(void *arg)
{
while(count < 10) {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&condition);
/* do more intelligent things here */
count++;
pthread_mutex_unlock(&mutex);
}
printf("Test signal thread finished\n");
return NULL;
}
int main(int argc, char **argv)
{
if(pthread_create(&thread_one_data, NULL, &cond_test_wait, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
if(pthread_create(&thread_two_data, NULL, &cond_test_signal, NULL)) {
fprintf(stderr, "Could not create thread, exiting!\n");
return -EXIT_FAILURE;
}
pthread_join(thread_one_data, NULL);
pthread_join(thread_two_data, NULL);
pthread_cond_destroy(&condition);
pthread_mutex_destroy(&mutex);
printf("Program ran succesfully!\n");
return -EXIT_SUCCESS;
}
Save in a file cond.c and compile & link using:
gcc -o cond -pthread -Os -Wall cond.c
Do note how neat condition work in this example. You can use them to wait until any expression (= condition) becomes true. After the condition becomes true normal execution continue's.
If you need any more help, don't hesitate to ask in the comments. Good luck combining the above examples to fix up your program.

Semaphore with different user does not work

I am working a c- project which uses semaphores to handle the same function at the same time. When I run it, on linux, under the root user, it works perfect. But if I run it on another user, the script isn't executed and it leaves a semaphore in the semaphore array. Does anybody know a solution to this problem?
Here is my code:
int main(int argC, char* argv[]) {
pthread_t thr[argC-1];
int indexes[argC-1];
int i,j;
for(j=0; j<(argC-1); j++) {
indexes[j] = atoi(argv[j+1]);
pthread_create (&thr[j], NULL, (int *) &stabtest, (void *) &indexes[j]);
}
sem_init(&mutex, 0, 1);
for(j=0; j<(argC-1); j++) pthread_join(thr[j], NULL);
// Destroy semaphore
sem_destroy(&mutex);
// Exit
exit(0);
}
int stabtest(void *ptr) {
sem_wait(&mutex); // down semaphore
// Other code ...
sem_post(&mutex); // up semaphore
pthread_exit(0); // exit thread
}
This code I actually found on the internet because I have no experience with semaphores. So I am not sure of this code is the right one to run the function in parallel at the same time. But it works for the root user, so I guess the code is more or less ok.
Thank you!
If this is the code you are using, whatever you think is happening isn't happening. Permissions should have no effect on the semaphore you are using. And there is no semaphore array, you are using a single semaphore.
You seem to have a shaky grasp on command line parms. They are an array pointers to string. argc is the number of arguments. There will always be at least 1 argv, argv[0], which is the program name. Please don't rename argc. Everyone knows what argc is. Renaming it will just annoy people.
You start your threads and then you initialize your semaphore. That's a problem.
The start function of a pthread has to have the signature void* stabtest(void *ptr). Yours is int stabtest(void *ptr) and you are trying to cast your way out of a mistake. Don't do that. If you want to return something from a thread you do it through the void ptr used as the 4th parm in pthread_create. That is, allocate some memory, pass it in pthread_create, do whatever you need to in the thread to change the information pointed to, and then return the same void ptr from the thread. When you do your pthread_join you can access the returned pointer to the data in the second paramater in pthread_join.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
void* stabtest(void *ptr)
{
sem_wait(&mutex); // down semaphore
printf("in thread %lu...\n", pthread_self());
sem_post(&mutex); // up semaphore
pthread_exit(0); // exit thread
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
printf("usage: %s numThread\n", argv[0]);
exit(1);
}
int maxThreads = atoi(argv[1]);
pthread_t thr[maxThreads];
int indexes[maxThreads];
int i, j;
sem_init(&mutex, 0, 1);
for (j = 0; j < maxThreads; j++)
pthread_create (&thr[j], NULL, stabtest, NULL);
for (j = 0; j < maxThreads; j++)
pthread_join(thr[j], NULL);
// Destroy semaphore
sem_destroy(&mutex);
// Exit
exit(0);
}

multithreading in C: passing a structure

I am learning multithreading performance in C. When I tried to write a sample code, I bumped into a problem:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct{
int a;
char b;
} args;
void* some_func (void* arg)
{
args *argsa = malloc(sizeof(args));
//copy the content of arg to argsa,
//so changes to arg in main would not affect argsa
*argsa = *(args*) arg;
int i = 10;
for (; i > 0; i--)
{
usleep (1); //to give other threads chances to cut in
printf ("This is from the thread %d\n", argsa->a);
}
free (argsa);
}
int main()
{
pthread_t thread[3];
args ss;
int index = 0;
ss.b = 's';
for (; index <3 ; index++)
{
ss.a = index;
if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
{
usleep(10);
printf ("something is wrong creating the thread");
}
}
pthread_join ( thread[0], NULL);
pthread_join ( thread[1], NULL);
pthread_join ( thread[2], NULL);
return 0;
}
I know char b in the struct is useless, but I just want to practice passing a structure.
I expect the code to print out "This is from the thread x", where x is 0, 1 or 2, alternatively. However, the code currently only gives me "This is from the thread 2" 30 times. I believe there is something wrong with
*argsa = *(args*) arg;
But I can't find a way to solve this and get the desired output.
Any help would be appreciated!
Because you are passing the same pointer to all the threads. By the time thread 0 has started, you have already incremented the value of ss.a to 1 (and then 2).
This is a bit more correct:
void* some_func (void* arg)
{
args *argsa = (args*)arg;
int i;
for (i = 0; i < 10; i++)
{
usleep (1); //to give other threads chances to cut in
printf ("This is from the thread %d\n", argsa->a);
}
}
int main()
{
pthread_t thread[3];
args ss[3];
int index;
for (index = 0; index < 3; index++)
{
ss[index].a = index;
if (pthread_create(&thread[index], NULL, some_func, &ss[index] ))
{
printf ("something is wrong creating the thread");
}
}
pthread_join ( thread[0], NULL);
pthread_join ( thread[1], NULL);
pthread_join ( thread[2], NULL);
return 0;
}
The pattern to use to solve this kind of problem is as follows:
Create a structure that will hold the parameters you want to pass to the thread.
Allocate such a structure with malloc.
Fill in the structure.
Pass the pointer to the structure to the thread.
When the thread is finished with the structure, the thread frees it.
This assumes you don't need to get any information back from the thread. If you do, you can change it so that the code that joins the thread frees the structure. That allows the structure to hold a reply as well -- you join the thread, read the response information, and then free the structure.
No special locking or synchronization is required because while the newly-created thread exists, it is the only thread that touches the structure.
Sorry guys, but I was trying to solve the same issue and I don't think a proper answer was given yet, in order to solve the problem. I tried this on my own and I came up with the following code. Now, I compiled and run it and it pretty worked as I expected, still I not that confident that the "lock in main and unlock in child process" is the most elegant solution, so I'd like to know what you think about it. Thank you very much in advance for any clarification.
Here is the code:
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct{
int a;
char b;
} args;
pthread_mutex_t lock;
void* some_func (void *arg) {
args argsa = *(args*)arg;
pthread_mutex_unlock(&lock);
printf ("This is from the thread %d\n", argsa.a);
}
int main() {
pthread_t thread[10];
args ss;
int i, index=0;
ss.b = 's';
if (pthread_mutex_init(&lock, NULL) != 0) {
printf("\n mutex init failed\n");
return 1;
}
for (index = 0; index < 10 ; index++)
{
pthread_mutex_lock(&lock);
ss.a = index;
printf("index=%d, ", ss.a);
if (pthread_create (thread+index, NULL, some_func, (void*)&ss ))
{
usleep(10);
printf ("something is wrong creating the thread");
}
}
for(i=0;i<10;i++)
pthread_join ( thread[0], NULL);
return 0;
}
Output:
#./program
index=0, This is from the thread 0
index=1, This is from the thread 1
index=2, This is from the thread 2
index=3, This is from the thread 3
index=4, This is from the thread 4
index=5, This is from the thread 5
index=6, This is from the thread 6
index=7, This is from the thread 7
index=8, This is from the thread 8
index=9, This is from the thread 9

Resources