POSIX pthread_join hangs after thousands of threads - c

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?

Related

I would like to get 4 separate prints: "This is a thread 1", "This is a thread 2" and so on

pthread_create in a for loop, this is my code
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex;
void* helloWorld(void *i) {
pthread_mutex_lock(&mutex);
printf("This is a thread %d\n", *((int*) i));
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
pthread_mutex_init(&mutex, NULL);
pthread_t threads[4];
int i;
printf("Main Message\n");
for (i = 0; i < 4; i++) {
pthread_create(&threads[i], NULL, helloWorld, &i);
}
for (i = 0; i < 4; i++) {
pthread_join(threads[i], NULL);\
}
pthread_mutex_destroy(&mutex);
return 0;
}
The order doesn't really matter as long as all 4 threads are working.
I've tried to use mutex but it didn't solve the issue.
My current output is pretty random, it can be 0000 or 0112 or anything else.
The problem is two-fold:
First of all you don't have control over when the threads run or in which order.
You pass the same pointer to all threads.
You can solve the second issue by passing the value if i to the threads. This is one of the few cases where it's considered okay to pass values instead of pointers:
pthread_create(&threads[i], NULL, helloWorld, (void*)(uintptr_t) i);
Then in the thread
printf("This is a thread %d\n", (int)(uintptr_t) i);
The first issue, about the order, you have to come up with some other way to synchronize the threads and how they notify each other. For example by using four condition signals, one for each thread, that you signal in the order you want the threads to execute.

Testing race condition

I just started learning about thread today, and wanted to test the race condition of threads by running two codes with/without mutex.
#define HAVE_STRUCT_TIMESPEC
#include <pthread.h>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define NTHREADS 3
#define ITERATIONS (long long) 1000000000
//pthread_mutex_t mutex;
static long long counter = 0;
static void * thread_f(void * arg) {
unsigned long long i;
(void)arg;
for (i = 0; i != ITERATIONS; i++) {
// pthread_mutex_lock(&mutex);
counter = counter + 1;
// pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void) {
pthread_t threads[NTHREADS];
int i;
for (i = 0; i != NTHREADS; i++)
pthread_create(&threads[i], NULL, thread_f, NULL);
for (i = 0; i != NTHREADS; i++)
pthread_join(threads[i], NULL);
printf("expected = %lld, actual = %lld\n", NTHREADS*ITERATIONS, counter);
printf("experienced %lld race conditions\n", NTHREADS*ITERATIONS - counter);
system("pause");
return 0;
}
So, without mutex, the program prints out these following lines on cmd:
expected = 3000000000, actual = 1174158414
experienced 1825841586 race conditions
However, if I put mutex in the code, and run the program, cmd pops up then shuts down itself without showing any result.
I want to know if I coded anything wrong or is misusing mutex lines as I really don't know much about threads.
p.s this is coded in windows 10, using visual studio
Thanks to EOF from the comment, I found out that I did not initialize mutex in the code.
I simply added:
if (pthread_mutex_init(&mutex, NULL)) {
printf("Something went wrong\n");
return 1;
}
this in the main, and everything works fine now.

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.

Segfault at pthread_join (only sometimes)

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;
}

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