Pass argument to multiple threads - c

New to C, I was reading here about how to properly pass an argument to a thread. What about if this argument needed to be passed to multiple threads? Where/how should I use free()? Say:
void *foo(void *i) {
int a = *((int *) i);
while(1){
printf("foo running \n");
sleep(1);
}
}
void *bar(void *i) {
int a = *((int *) i);
while(1){
printf("bar running \n");
sleep(1);
}
}
int main() {
pthread_t threads[2];
int i;
for (i = 0; i < 2; i++ ) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(1);
}
*arg = i;
pthread_create(&threads[0], NULL, foo, arg);
pthread_create(&threads[1], NULL, bar, arg);
}
for (i = 0; i < 2; i++){
pthread_join(threads[i],NULL);
}
return 0;
}
Is calling free(arg); in main after spawning the threads the same thing / safe?

If all threads needs the exact same argument, and they are not modifying the argument, there's no need to allocate it dynamically at all, instead just declare it as a variable at function scope in the main function. If there's no dynamic allocation, there's no need to free it.
On the other hand if you need separate arguments in a loop like you do, you need to keep track of all arguments, for example using an array:
// Rest of program...
#define NUMBER_OF_ITERATIONS 2
int main(void)
{
int args[NUMBER_OF_ITERATIONS];
pthread_t threads[NUMBER_OF_ITERATIONS][2];
// Create threads
for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
args[i] = i;
pthread_create(&threads[i][0], NULL, foo, &args[i]);
pthread_create(&threads[i][1], NULL, bar, &args[i]);
}
// Wait for threads to finish
for (unsigned i = 0; i < NUMBER_OF_ITERATIONS; ++i)
{
pthread_join(threads[i][0]);
pthread_join(threads[i][1]);
}
return 0;
}
The program above also solves another problem you have, when you create a total of four threads but only join two.

You need to make sure both threads have finished before calling free(arg).
That means you can do it after you call pthread_join on both threads.
for (i = 0; i < 2; i++){
pthread_join(threads[i],NULL);
}
free(args);

Related

pthread_join constantly causes segfault

This issue is definitely the source of a stupid mistake, but for the life of me I cannot get to the bottom of it.
I'm writing a much larger program, but I've narrowed down a constant segfault error that is coming up whenever I call pthread_join. I've included the relevant code below, hopefully someone can help me figure out what I'm doing wrong. Cheers :)
Functions for managing pthreads
void *scalloc(size_t nmemb, size_t size)
{
void *p;
p = calloc(nmemb, size);
if (p == NULL)
sys_error("Error allocating memory block (calloc).", 1);
return p;
}
pthread_t *new_thread_array(int n)
{
return scalloc(n, sizeof(pthread_t));
}
int spthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
int ret;
if ((ret = pthread_create(&thread, attr, start_routine, arg)) != 0)
sys_error("Error at pthread_create.", ret);
return 0;
}
int spthread_join(pthread_t thread, void **retval)
{
int ret;
if ((ret = pthread_join(thread, retval)) != 0)
sys_error("Error at pthread_join.", ret);
return 0;
}
int create_threads(pthread_t *thread_arr, int n, const pthread_attr_t *attr,
void *(*start_routine) (void *), void **arg_arr)
{
for (int i = 0; i < n; i++) {
spthread_create(&thread_arr[i], attr, start_routine, arg_arr[i]);
debug("created thread %d", i);
}
return 0;
}
int join_threads(pthread_t *thread_arr, int n, void **ret_arr)
{
debug("Starting join");
for (int i = 0; i < n; i++) {
if (ret_arr != NULL)
spthread_join(thread_arr[i], ret_arr[i]);
else {
debug("Attempting to join %d", i);
spthread_join(thread_arr[i], NULL);
debug("Joined %d", i);
}
}
return 0;
}
Test code that produces the error
void *threadfunc(void *id)
{
fflush(stdout);
fprintf(stdout, "Thread %d printing.\n", *(int *)id);
fflush(stdout);
return;
}
int threadtest(int nodes)
{
int ret;
int *targs = scalloc(nodes, sizeof(int));
int *pass[nodes];
for (int i = 0; i < nodes; i++) {
targs[i] = i;
pass[i] = &targs[i];
}
printf("Starting L1 thread test...\n");
pthread_t *threads = new_thread_array(nodes);
debug("Allocated pthread array for %i threads.", nodes);
create_threads(threads, nodes, NULL, &threadfunc, pass);
join_threads(threads, nodes, NULL);
debug("Successfully joined %i threads.", nodes);
free(targs);
free(threads);
return 0;
}
int main()
{
return threadtest(5);
}
Finally, here is the output of running the function threadtest, confirming that the segfault (appears) to occur in the parent thread, at the call to pthread_join.
Starting L1 thread test...
Allocated pthread array for 5 threads.
created thread 0
created thread 1
Thread 0 printing.
created thread 2
Thread 1 printing.
Thread 2 printing.
created thread 3
Thread 3 printing.
created thread 4
Thread 4 printing.
Starting join
Attempting to join 0
zsh: segmentation fault ./tests/L1tests

pthread_mutex_t inside a structure and locking the structure when accessing

I have global structure pointer which i have done a malloc (array of 10 structures) and i have sent one instance of this structure to each thread, and before passing this structure instance as argument to pthread_create(), am updating the structure member value. Inside each thread i will lock and print the member value.
I have created another thread, in which i am passing the entire structure instance, i am locking each structure instance and printing it, but every time it prints 0. Can you please suggest what changes i have to make.
I dont want to use any thread conditions, as i am sleeping in each thread for a thread switch.
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
struct lock_check{
int value;
pthread_mutex_t lock;
};
struct lock_check *check;
void* trythis(void *arg)
{
struct lock_check *thread = (struct lock_check *)arg;
while(1){
pthread_mutex_lock(&thread->lock);
printf("Inside Thread with value:%d\n", thread->value);
pthread_mutex_unlock(&thread->lock);
sleep(1);
}
return NULL;
}
void* printthis(void *arg)
{
printf("Entering printthis thread\n");
struct lock_check *print_thread = (struct lock_check *)arg;
for(int i = 0; i < 10; i++){
pthread_mutex_lock(&print_thread[i].lock);
printf("Printing value :%d\n", print_thread[i].value);
pthread_mutex_unlock(&print_thread[i].lock);
}
return NULL;
}
int main(void)
{
int i = 0;
int error;
check = malloc(sizeof(struct lock_check) * 10);
pthread_t tid[10];
pthread_t tid_read;
for (int i = 0; i < 10; i++) {
check[i].value = i;
error = pthread_create(&(tid[i]), NULL, &trythis, &check[i]);
if (error != 0)
printf("\nThread can't be created :[%s]", strerror(error));
}
sleep(5);
printf("creating printthis thread\n");
error = pthread_create(&tid_read, NULL, &printthis, &check);
for (int i = 0; i < 10; i++) {
pthread_join(tid[i], NULL);
}
pthread_join(tid_read, NULL);
return 0;
}
error = pthread_create(&tid_read, NULL, &printthis, &check);
pthread_create is expecting void * but you are passing struct lock_check ** having undefined behavior.
Change it to.
error = pthread_create(&tid_read, NULL, &printthis, check);

pthread does not exit in C

I am writing a multi-threaded application that reads a file and seeks for a word in chunks of it a thread has in memory.
A thread needs to asynchronously close other threads looking for that word if it is first to find it.
The problem is when a word is found and other threads are being closed the program does not terminate (in 6 out of 10 executions). I have checked in gdb that one thread does not exit. It happens even when I do not call waitforthreads(n_threads).
// [...]
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads;
int allread;
// [...]
int main(int argc, char* argv[]) {
// [...]
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
pthread_mutex_init(&mutex, NULL);
runthreads(f, word, n_threads, n_records);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
// [...]
}
void runthreads(FILE* f, char* w, int n_threads, int n_records) {
struct targs_t args = {w, n_records};
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, findword, (void*) &args);
}
void waitforthreads(int N) {
for (int i=0; i<N; i++)
if(pthread_join(threads[i], NULL))
exit_(6);
}
void* findword(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
struct targs_t* args = (struct targs_t*) arg;
int max_length = args->n_records * sizeof(record_t);
record_t* records = malloc(max_length);
int found = 0;
while (!allread && !found) {
pthread_mutex_lock(&mutex);
// allread is being set in the function below
// if the whole file has been read
readRecords((char*) records, args->n_records, f);
pthread_mutex_unlock(&mutex);
for (int i=0; i<args->n_records; i++)
if (strlen(records[i].text) == 0) break;
else if (strstr(records[i].text, args->word) != NULL) {
notifyfound(pthread_self(), records[i].id);
found = 1;
break;
}
}
free(records);
return NULL;
}
void notifyfound(pthread_t tid, int id) {
printf("Found: %d (%ld)\n", id, (long) tid);
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing %ld\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
printf(" finished closing\n");
}
This has to do with cancellation points, although the specifics are hard to come by since you haven't shared a minimal example. My diagnosis is either
6/10 times you have at least one thread waiting for a mutex, and other one in readRecords, which will cancel and not free the mutex. Setup cancellation handlers with pthread_cleanup_push and pthread_cleanup_pop which will free your mutex, and read the manual for pthread_cancel. See related pthread_cleanup_push causes Syntax error for some references.
Some of your threads are not detecting the cancellation - try using pthread_testcancel to setup a guaranteed cancellation point.
Here is some code that fixes these sorts of problems, by adding a cancellation check and mutex cleanup.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
FILE* f;
pthread_mutex_t mutex;
pthread_t* threads;
int n_threads = 3;
int allread;
long int count = 0;
int *thread_ids;
int global_quit = 0;
#define MAX 99999
void waitforthreads(int N) {
printf("waiting for %d threads\n", N);
for (int i=0; i<N; i++)
{
printf("thread %d | %d\n", i, threads[i]);
if(pthread_join(threads[i], NULL))
{
printf("problem\n");
exit(6);
}
}
printf("done.\n");
}
void notifyfound(pthread_t tid, int count) {
printf("%d | %d got big number\n", count, pthread_self());
for (int i=0; i<n_threads; i++)
if (threads[i] && !pthread_equal(threads[i], tid)) {
printf(" closing '%ld'\n", (long) threads[i]);
pthread_cancel(threads[i]);
}
global_quit = 1;
printf(" finished closing\n");
}
void waiting_thread_cleanup(void *arg)
{
pthread_mutex_unlock((pthread_mutex_t *)arg);
}
void* do_thing(void* arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
int* id = (int *)arg;
int quit = 0;
while (!allread) {
pthread_mutex_lock(&mutex);
pthread_cleanup_push(waiting_thread_cleanup, (void *)&mutex); /* must be paired with pop. */
if(count++==MAX)
{
notifyfound(pthread_self(), *id);
quit=1;
}
else if(count % 10000 == 0)
printf("[%d] - %d\n", *id, count);
pthread_testcancel(); /* required to allow for the cancel to ever be 'detected' other functions are sufficient as well. */
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(1); /* if this isn't here, this will occassionally hand because the mutex isn't freed. */
if(quit==1)
{
printf("%d | %d quitting\n", *id, pthread_self());
break;
}
}
return NULL;
}
void runthreads(FILE* f, int n_threads) {
for (int i=0; i<n_threads; i++)
pthread_create(&threads[i], NULL, do_thing, &(thread_ids[i]));
}
int main(int argc, char* argv[]) {
threads = (pthread_t*) calloc(n_threads, sizeof(pthread_t));
thread_ids = (int*) calloc(n_threads, sizeof(int));
for(int i=0;i<n_threads;i++)
thread_ids[i] = i;
pthread_mutex_init(&mutex, NULL);
runthreads(f, n_threads);
waitforthreads(n_threads);
pthread_mutex_destroy(&mutex);
}

C - Waiting For Multiple Threads to Terminate

I am trying to wait for all the threads to terminate before the main() process terminates. Here is what I have so far:
void* mapperFunction()
{
printf("Hello\n");
return NULL;
}
int main()
{
int i; // Used in "for" loops.
int N = 3;
pthread_t* mapperThreads = (pthread_t*) malloc(sizeof(pthread_t) * N);
for ( i = 0; i < N; i++)
{ // Creates all the mapper threads.
pthread_create( &mapperThreads[N], NULL, mapperFunction, NULL);
}
for ( i = 0; i < N; i++)
{ // Waits for all the mapper threads to terminate.
pthread_join( mapperThreads[N],NULL);
}
return 0;
}
I get three different outputs when I run this code;
1- Hello\n
2- Helle\nHello\n
3- Hello\nHello\nHello\n
It looks like the main() process does not always wait for all threads to terminate. What am I doing wrong?
You want &mapperThreads[i] instead of &mapperThreads[N] in each case.
Maybe pthread_barrier_wait is what you're looking for ?
Link

Thread Termination Condition

I'm writing a producer-consumer thread program in C. Everything in my program is working perfectly with one major exception. When I have more than one consumer thread, which is pretty much always, only the first consumer thread will actually terminate. I've tried absolutely everything that I can think of, but the problem persists. Here's my code, with the guts of it stripped out, so that you can see just the part that is relevant.
I can see from my output that both of the termination condition variables become zero, which is of course why the first consumer thread terminates. But why don't the other consumer threads also terminate?
Thank you!
sem_t full, empty, mutex;
int threads;
int to_consume;
FILE* inputfp[5];
FILE* outputfp = NULL;
char in[BUF];
void* p(void* inpFile) {
while (fscanf(inpFile, FMTSTRING, in) > 0) {
sem_wait(&empty);
sem_wait(&mutex);
// production code here
to_consume++;
sem_post(&mutex);
sem_post(&full);
}
fclose (inpFile);
sem_wait(&mutex);
threads--;
sem_post(&mutex);
return NULL;
}
void* c() {
int continuing = 1;
while (continuing) {
sem_wait(&full);
sem_wait(&mutex);
//consumption code here
to_consume--;
fprintf("%d %d\n", threads, to_consume); //these both go to zero by the end
if ( (threads <= 0) && (to_consume <= 0) ) {
continuing = 0;
}
sem_post(&mutex);
sem_post(&empty);
}
return NULL;
}
int main (int argc, char* argv[]) {
int i;
int con_threads;
con_threads = 3;
to_consume = 0;
pthread_t *pr_thread[argc-2];
pthread_t *con_thread[2];
sem_init(&full, 0, 0);
sem_init(&empty, 0, 50);
sem_init(&mutex, 0, 1);
for (i = 0; i < (argc-2); i++) {
pr_thread[i] = (pthread_t *) malloc(sizeof(pthread_t));
inputfp[i] = fopen(argv[i+1], "r");
int rc = pthread_create (pr_thread[i], NULL, p, inputfp[i]);
sem_wait(&mutex);
threads++;
sem_post(&mutex);
}
outputfp = fopen(argv[(argc-1)], "wb");
for (i = 0; i con_threads 3; i++) {
con_thread[i] = (pthread_t *) malloc(sizeof(pthread_t));
int rc = pthread_create (con_thread[i], NULL, c, NULL);
}
for (i = 0; i < (argc - 2); i++) {
pthread_join(*pr_thread[i], 0);
free(pr_thread[i]);
}
for (i = 0; i con_threads 3; i++) {
fprintf(stderr, "About to close consumer thread %d.\n", i);
pthread_join(*res_thread[i], 0);
fprintf(stderr, "Consumer thread %d closed successfully.\n", i);
free(res_thread[i]);
}
printf ("About to close the output file.\n");
/* Close the output file */
fclose (outputfp);
return EXIT_SUCCESS;
}
I think your problem is that you don't post full again when the first consumer detects that there are no threads left, so the second consumer is waiting on full but the signal will never arrive. You may need a count of the consumers, though for a first pass (proof of concept), you can leave full with a post that is never read.

Resources