I'm trying to implement a variation of the readers and writers problem in C, the variation is that writers can either be incrementers or decrementers and they should keep a running count. Below is the code I am trying to implement, I am getting the error "Segmentation Fault (core dumped). I have attempted to debug and received this feedback from gdb - #0 0x0000000000400d84 in main ().
I'd appreciate it if someone were able to explain this to me/give me tips on how to fix this fault.
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define WAIT 20
#define NEW 0
#define DECREMENT 0
#define INCREMENT 1
#define TIME 5
#define VALUE 1
#define COMMON 0
int readerCount = NEW;
int total = 0;
int v;
sem_t mutex;
sem_t access_data;
int increment_or_decrement() {
int d;
return d = rand() % 2;
}
void *writer(void *arg) {
int version = increment_or_decrement();
int *iID = (int *) arg;
int *dID = (int *) arg;
sleep(rand() % WAIT);
sem_wait(&access_data);
if (version == INCREMENT) {
fprintf(stderr, "Incrementer %d accessed the data\n", *iID);
total++;
fprintf(stderr, "Total: %d\n", total);
}
else {
fprintf(stderr, "Decrementer %d accessed the data\n", *dID);
total--;
fprintf(stderr, "Total: %d\n", total);
}
sleep(TIME);
sem_post(&access_data);
pthread_exit(NULL);
}
void *reader(void *arg) {
int *id = (int *) arg;
sleep(rand() % WAIT);
while(1) {
if (readerCount == NEW) {
sem_wait(&mutex);
v = version;
readerCount++;
if (readerCount == 1)
sem_wait(&access_data);
sem_post(&mutex);
fprintf(stderr, "Reader %d accessed the data\n", *id);
sem_wait(&mutex);
readerCount--;
if(readerCount == NEW)
sem_post(&access_data);
sem_post(&mutex);
pthread_exit(NULL);
}
}
}
int main() {
int numReaders = rand();
int numWriters = rand();
int i;
sem_init(&mutex, COMMON, VALUE);
sem_init(&access_data, COMMON, VALUE);
pthread_t readers[numReaders];
pthread_t writers[numWriters];
int readerID[numReaders];
int writerID[numWriters];
for (i = 0; i < numReaders; i++)
readerID[i] = i;
for (i = 0; i < numWriters; i++)
writerID[i] = i;
for (i = 0; i < numReaders; i++) {
if(pthread_create(&readers[i], NULL, reader, (void *) &readerID[i]) != 0) {
printf("Child failed\n");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numWriters; i++) {
if (pthread_create(&writers[i], NULL, writer, (void *) &writerID[i]) != 0) {
printf("Child failed\n");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numReaders; i++) {
if (pthread_join(readers[i], NULL) != 0) {
printf("Join failed\n");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < numWriters; i++) {
if (pthread_join(writers[i], NULL) != 0) {
printf("Join failed\n");
exit(EXIT_FAILURE);
}
}
sem_destroy(&access_data);
sem_destroy(&mutex);
}
You are likely to run out of stack space if rand returns big number as indicated in comments by #WhozCraig
If you just assign some finite values instead of using rand here:
int numReaders = rand();
int numWriters = rand();
I see it running without segmentation fault
Suspect: pthread_join(readers[i], NULL)
The second argument to pthread_join should be a valid address of a var to contain address of the return value from the exiting child threads. In this case, when a child thread exits, the pthread_exit tries to write NULL at NULL, and i think that is causing seg fault. Try changing NULL to some valid address in pthread_join for both readers and writes and see if it works.
EDIT: it turns out that POSIX allows passing NULL to pthread_join (see comments below), so suspect is acquitted.
Related
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
I tried to simulate the producer consumer problem using bounder buffer in C and threads.
Mutex and semaphores are also used.
The expected output is to display the state of buffer every time an item is produced or consumed.
Buffer size is fixed as 10. Initially buffer items are all -1. When a producer produces an item into it, the item replaces -1.
Item in 0th index is 0 ,1st index is 1 and so on.....which doesn't matter.
The program asks the number of producers and consumer we want to create.
The production is working fine....but not consumption.
Segmentation fault arises in Thread 1.I am not sure what Thread 1 is.
I tried to debug using GDB many times....without no hope.
// Producer consumer.
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <unistd.h>
#define TRUE 1
int buff_size=10,i;
int buffer[25];
pthread_mutex_t mutex;
sem_t full, empty;
int counter = 0;
int consume_count=0; //No of Consumers created
int produce_count=0; //No of Producers created
void initializeData()
{
sem_init(&full, 0, 0);
sem_init(&empty, 0, buff_size);
pthread_mutex_init(&mutex, NULL);
}
int insert_item(int counter)
{
if (counter < buff_size) {
buffer[counter] = counter;
counter++;
//produce_count++;
return 0;
}
else {
printf("\n[BUFFER FULL!]");
return -1;
}
}
int remove_item()
{
printf("\n[GOING TO REMOVE AN ITEM]\n");
if (buffer[counter-1] != -1) {
buffer[counter-1] = -1;
counter--;
//consume_count++; // Commented out...
return 0;
}
else {
printf("\n[EMPTY]\n");
return -1;
}
}
void *producer(void *arg)
{
int RET = 0;
while( TRUE ) {
sem_wait(&empty);
pthread_mutex_lock(&mutex);
RET = insert_item(counter);
if (RET){
printf("\nProducer Sleeping...zzZZ\n");
sleep(2);
}
pthread_mutex_unlock(&mutex);
sem_post(&full);
if(!RET)
printf("\n[ INSERTED ]\n" );
printf("\n");
for(i=0; i < buff_size ;i++)
printf("[%d] ",buffer[i]);
printf("\n");
sleep(3);
} // end of while...
}
void *consumer(void *arg)
{
int RET = 0;
while( TRUE ) {
sem_wait(&full);
pthread_mutex_lock(&mutex);
RET = remove_item(buffer);
if (RET){
printf("\nConsumer Sleeping\n");
sleep(3);
}
pthread_mutex_unlock(&mutex);
sem_post(&empty);
if(!RET) {
printf("\nConsumed\n");
printf("\n");
}
for(i=0 ; i < buff_size ; i++)
printf("%4d",buffer[i]);
printf("\n");
sleep(2);
} //end of while...
}
void main()
{
int produce, consume;
pthread_t *prod;//thread ID
pthread_t *cons;//thread ID
printf("\nEnter the no of producers: ");
scanf("%d",&produce);
printf("\nEnter the no of consumers: ");
scanf("%d",&consume);
putchar('\n');
for (i=0; i < buff_size; i++)
buffer[i] = -1;
for (i=0; i < buff_size; i++)
printf("[%d] ", buffer[i]);
printf("\n");
initializeData();
for (i = 0; i < produce; i++)
{
pthread_create(&prod[i], NULL, producer, NULL);
produce_count++;
}
for (i = 0; i < consume; i++)
{
pthread_create(&cons[i], NULL, consumer, NULL);
consume_count++;
printf("AAAAA");
}
/*for (i = 0; i < produce; i++)
pthread_join(producer, NULL);
for (i = 0; i < consume; i++)
pthread_join(consumer, NULL);*/
printf("\n===============\n[ PRODUCED: %d ]", produce_count);
printf("\n[ CONSUMED: %d ]\n==============", consume_count);
}
pthread_create(&prod[i], NULL, producer, NULL);
In this call pthread_create will create new thread and try to return thread id in prod[i]
But:
pthread_t *prod;//thread ID
pthread_t *cons;//thread ID
These are uninitiaised pointers, if you want to collect threadids in them, you need to allocate memory to them with malloc like:
prod = malloc(sizeof(pthread_t) * produce);
cons = malloc(sizeof(pthread_t) * consume);
Otherwise pthread_create will be storing threadid in invalid memory leading to segment fault
Hi I am bit new to C programming. Facing problem with producer consumer problem. When ever I try running the below code i get segmentation fault (core dumped). Please suggest where I am going wrong. But this code works for one consumer but for multiple consumer it is throwing error.
Code:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define MAXNITEMS 20
#define MAXNTHREADS 5
void *produce(void *arg);
void *consume(void *arg);
/* globals shared by threads */
int nitems=MAXNITEMS; /* read-only by producer and consumer */
int buff[MAXNITEMS];
int Nsignals;
struct {
pthread_mutex_t mutex;
int buff[MAXNITEMS];
int nput; /* next index to store */
int nval; /* next value to store */
} put = { PTHREAD_MUTEX_INITIALIZER };
/** struct put is used by producer only ***/
struct{
pthread_mutex_t mutex;
pthread_cond_t cond;
int nready; /* number ready for consumer */
} nready = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,0};
int main(int argc, char **argv)
{
int i, prod, con;
pthread_t tid_produce[MAXNTHREADS], tid_consume[MAXNTHREADS];
printf("Enter the number of producers : \n");
scanf("%d",&prod);
printf("Enter the number of consumers: \n");
scanf("%d",&con);
/* create all producers and consumers */
for (i = 0; i < prod; i++)
{
printf("1 %d\n", i);
pthread_create(&tid_produce[i], NULL,produce, NULL);
}
for (i = 0; i < con; i++) {
printf("2 %d\n", i);
pthread_create(&tid_consume[i], NULL, consume, NULL);
}
for (i = 0; i < prod; i++) {
printf("3 %d\n", i);
pthread_join(tid_produce[i], NULL);
}
for (i = 0; i < con; i++) {
printf("4 %d\n", i);
pthread_join(tid_consume[i], NULL);
}
exit(0);
}
void *produce(void *arg)
{
for ( ; ; )
{
pthread_mutex_lock(&put.mutex);
if (put.nput >= nitems) {
pthread_mutex_unlock(&put.mutex);
return(NULL); /* array is full, we're done */
}
put.buff[put.nput] = put.nval;
printf ("producer %lu produced :%d \n",pthread_self(), put.buff[put.nput]);
put.nput++;
put.nval++;
printf("outside producer lock\n");
pthread_mutex_unlock(&put.mutex);
*((int *) arg) += 1;
}
}
void *consume(void *arg)
{
int i;
for (i = 0; i < nitems; i++) {
pthread_mutex_lock(&nready.mutex);
while (nready.nready == 0){
pthread_cond_wait(&nready.cond,&nready.mutex);
}
printf ("consumer %lu consumed %d \n", pthread_self(),nready.nready);
nready.nready--;
pthread_mutex_unlock(&nready.mutex);
if (buff[i] != i)
printf("buff[%d] = %d\n", i, buff[i]);
}
return(NULL);
}
*((int *) arg) += 1 inside produce(...) causes the segmentation fault. Because pthread_create(&tid_produce[i], NULL,produce, NULL); passes NULL as arg.
So we need to allocate some memory for arg.
// main
int i, prod, con;
pthread_t tid_produce[MAXNTHREADS], tid_consume[MAXNTHREADS];
int p_arg[MAXNTHREADS]; // <======
// ...
for (i = 0; i < prod; i++)
{
pthread_create(&tid_produce[i], NULL,produce, p_arg+i); // <====
}
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);
}
I keep getting a seg fault (core dump) after pthread_join in my program. It prints out the expected result just fine, but seg faults when joining the thread. I have looked at several other discussions on this topic, but none of the suggested solutions seem to work in my case. Here is what my compile command looks like (no compile warnings or errors):
$ gcc -Wall -pthread test.c -o test
Here is the output:
$ ./test
1 2 3 4 5 6 7 8 9 10
Segmentation fault (core dumped)
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
void *fillArray(int *size) {
int i;
for (i = 0; i < *size; i++) {
array[i] = i+1;
}
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
rc = pthread_create(&thread, NULL, fillArray(&size), &res);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Any ideas what could be the cause?
This doesn't compile for me: It fails with
dummy.cpp: In function ‘int main(int, char**)’:
dummy.cpp:29: error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
dummy.cpp:29: error: initializing argument 3 of ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
Which is because you're actually calling fillArray and passing its result to pthread_create, rather than passing the function pointer. I expect your code will need to look more like this (UNTESTED!) : (Note I changed signature of fillArray, created data struct type to pass to fillArray, changed how pthread_create is called)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
struct fillArrayData {
int * array;
int size;
int * result;
};
void *fillArray(void *void_data) {
fillArrayData * data = (fillArray*)void_data;
for (int i = 0; i < data.size; i++) {
data.array[i] = i+1;
}
//You could fill in some return info into data.result here if you wanted.
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
fillArrayData data;
data.array = array;
data.size = 10;
rc = pthread_create(&thread, NULL, fillArray, &data);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Error in
Calling function pointer
passing parameter to thread handler
In pthread prototype of pthread_create below
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
1st argument - pthread_variable
2nd argument - thread attrubutes
3rd argument - thread handler(function pointer name)
4th argument - variable need to pass thread handler.
In 4th argument - if two thread want to share single variable, then create global variable, and the pass this variable when creating thread.
sample program:
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
further details here