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
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'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.
I have written the code below but when I run it it brings segmentation fault. It compiles correctly though. Where are my mistakes?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char buf[123];
snprintf(buf, sizeof(buf), "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
pthread_t *pt = NULL;
for (i = 0; i < N; i++) {
pthread_create(pt, NULL, run, &i);
}
return EXIT_SUCCESS;
}
Any hint is welcomed.
Thank you
You have serveral issues:
1) You are passing a NULL to pthread_create() which is probably the reason for segfault.
2) You don't wait for the threads to complete (when main thread exits the whole process dies).
3) You are passing the address same variable i to all threads. This is a data race.
4) You are returning the address of a local variable buf from the thread function.
You can fix it like:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
static int N = 5;
static void* run(void *arg) {
int *i = (int *) arg;
char *buf = malloc(16);
snprintf(buf, 16, "thread %d", *i);
return buf;
}
int main(int argc, char *argv[]) {
int i;
void *ret;
int arr[N];
pthread_t pt[N];
for (i = 0; i < N; i++) {
arr[i] = i;
pthread_create(&pt[i], NULL, run, &arr[i]);
}
for (i = 0; i < N; i++) {
pthread_join(pt[i], &ret);
printf("Thread %d returned: %s\n", i, (char*)ret);
free(ret);
}
return EXIT_SUCCESS;
}
Note that you don't need to use pthread_join() calls. You can also cal pthread_exit() from the main thread so that only the main thread exit and other threads continue.
I'm meeting a problem with this code which is a basic code from my books to help understand how the threads works. It's is supposed to create NTHREADS which should execute the neg function and then return the opposite of the argument received
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define NTHREADS 2
void *neg (void * param);
int main(int argc, char * argv[]){
pthread_t threads[NTHREADS];
int arg [NTHREADS];
int err;
long i;
for(i = 0; i< NTHREADS; i++){
arg[i] = i;
err= pthread_create(&(threads[i]), NULL, &neg, (void *) &(arg[i]));
if(err =! 0){
error(err,"pthread_create");
}
}
int j;
for (j = 0; j < NTHREADS; j++){
int *r;
err= pthread_join(threads[j], (void **) &r);
printf("Resultat [%d] = %d \n", j, *r);
free(r);
if(err!=0){
error(err,"pthread_join");
}
}
return(EXIT_SUCCESS);
}
void *neg (void * param){
int *l;
l= (int *) param;
int *r= (int *) malloc(sizeof(int));
*r = -*l;
return ((void *) r);
}
When compiling I receive this message:
nico#nico-G56JR:~/Desktop$ gcc -pthread Threads.c
nico#nico-G56JR:~/Desktop$ ./a.out
./a.out: c: Unknown error 4196644
I can't find the mistake, can someone help me?
Thanks in advance
This
if(err =! 0){
should be
if(err != 0){
It is a bit of bad luck really, because err =! 0 actually compiles, assigning err a not zero value, which then falls into the error case passing something into the error function that is not really meaningful for your code.
I am trying to create a thread and from what I remember this should be the right way to do it:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
int SharedVariable =0;
void SimpleThread(int which)
{
int num,val;
for(num=0; num<20; num++){
if(random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val+1;
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
}
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, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
And the error that I'm getting is this one:
test.c: In function ‘main’: test.c:28: warning: passing argument 3 of
‘pthread_create’ from incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘void * (*)(void *)’ but
argument is of type ‘void (*)(int)’
I cannot change the SimpleThread function so changing the type of the parameter is not an option even though I already tried and it didn't work either.
What am I doing wrong?
SimpleThread should be declared as
void* SimpleThread(void *args) {
}
When you pass parameters to your thread, it is best to define a struct for them, pass a pointer to that struct as void*, and cast back to the right type inside the function.
Here's a compiling and "working" version of your program, although I have to admit to not knowing exactly what it's doing. For the critics in the audience, I apologize in advance for the pthread_join loop at the end.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
struct my_thread_info {
long which;
};
int SharedVariable = 0;
void *SimpleThread(void *data)
{
int num, val;
struct my_thread_info *info = data;
for (num = 0; num < 20; num++) {
if (random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %ld sees value %d\n", info->which, val);
SharedVariable = val + 1;
}
val = SharedVariable;
printf("Thread %ld sees final value %d\n", info->which, val);
free(info);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
struct my_thread_info *info;
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
info = malloc(sizeof(struct my_thread_info));
info->which = t;
rc = pthread_create(&threads[t], NULL, SimpleThread, info);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < NUM_THREADS; t++) {
pthread_join(threads[t], NULL);
}
}