I have done the following code.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
struct foo
{
int a;
int b;
};
void* thread_func1(void *arg)
{
struct foo *temp = (struct foo*)malloc(sizeof(struct foo));
temp->a = 10;
temp->b = 20;
pthread_exit(temp);
}
void* thread_func2(void *arg)
{
pthread_exit((void*)100);
}
int main()
{
pthread_t tid1, tid2;
int err;
struct foo *f;
void *ret;
err = pthread_create(&tid1, NULL, thread_func1, NULL);
err = err | pthread_create(&tid2, NULL, thread_func2, NULL);
if(err != 0)
{
perror("pthread_create()");
exit(-1);
}
err = pthread_join(tid1, (void**)&f);
if(err != 0 )
{
perror("pthread_join1");
exit(-1);
}
printf("a = %d, b = %d\n", f->a, f->b); //Line1
err = pthread_join(tid2, &ret);
if(err != 0 )
{
perror("pthread_join2");
exit(-1);
}
printf("ret = %d\n", *(int*)ret); //Line2
return 0;
}
I get segmentation fault on Line2. What is wrong with Line2
If i modify Line2 to
printf("ret = %d\n", (int)ret);
there is no segmentation fault and it prints the correct value(ie, 100). I do not understand why the modification works. I believe i have the wrong concept regarding the usage of double pointers. I would like to get it corrected.
What is the reason for the Segmentation fault and why the modification works?
That's because you are returning the actual integer, not a pointer, but you access it as a pointer.
You return one number from the thread. In the first thread, that number is a struct foo *. Therefore, if you say
pthread_join(tid1, &ret);
then ret will contain that pointer (which is not a double pointer).
Similarly in the second case, you are returning 100 even though you are looking at it as if it's a void *. Nevertheless, the value is still 100!
Therefore when you write
pthread_join(tid2, &ret);
ret will contain 100, which is not a pointer, but a mere integer. That is why you should also cast it to int.
The reason you got a segmentation fault is that you look at 100 as an int * and then try to dereference it.
pthread_exit((void*)100); causes integer 100 to become exit status of your thread. It just abuses type cast so that void* is its type.
If you want to retrieve this value, you will have to use same type cast abuse in main thread as well:
int ret;
err = pthread_join(tid2, (void**) &ret);
// here you can work with ret as with any other integer
I also suggest you to use return instead of pthread_exit. Also note that memory dynamically allocated by using malloc should be freed by calling free. And type cast of return value of malloc is redundant here, it can be omitted.
This question could also help you: Close a thread when done with it
Its because you're trying to dereferencce a pointer whose address is 100.
Instead of looking at the return value, why dont you pass in a pointer to what you want to assign in the thread_funcs? That is, use the "void *arg" arguments of thread_func1() and thread_func2()
Like this:
void* thread_func1(void *arg)
{
struct foo **fooPtrPtr = (struct foo**) arg;
*fooPtrPtr = (struct foo*)malloc(sizeof(struct foo));
...
}
void* thread_func2(void *arg)
{
int *intPtr = arg;
*intPtr = 100;
...
}
int main()
{
pthread_t tid1, tid2;
int err;
struct foo *f;
int ret;
err = pthread_create(&tid1, NULL, thread_func1, &f);
err = err | pthread_create(&tid2, NULL, thread_func2, &ret);
...
printf("a = %d, b = %d\n", f->a, f->b); //Line1
...
printf("ret = %d\n", ret); //Line2
...
}
Related
I have 2 threads and they should use the same memory. Main method should start both threads. Trå A must read the contents of a file and share it with Trå B. Trå B must also receive the data that Trå A has shared and loop through and count the number of bytes in the file. Both Threads run but on the last step before the program terminates before I memory segment fault. I use Semaphore to communicate between the Threads. here i my code:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFFER_SIZE 4096
typedef struct _Buffer
{
int size;
char data[BUFFER_SIZE];
} Buffer;
sem_t task1, task2;
void *thread_A(void *arg);
void *thread_B(void *arg);
int main(int argc, char *argv[])
{
Buffer *memory = malloc(sizeof(Buffer));
sem_init(&task1, 0, 0);
sem_init(&task2, 0, 0);
pthread_t thread_A_id;
pthread_t thread_B_id;
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
if (pthread_join(thread_A_id, NULL) != 0)
{
perror("Error joining thread A");
exit(1);
}
if (pthread_join(thread_B_id, NULL) != 0)
{
perror("Error joining thread B");
exit(1);
}
free(memory);
return 0;
}
void *thread_A(void *arg)
{
Buffer *buffer = (Buffer*) arg;
FILE *pdf_file = fopen("file.pdf", "rb");
if (pdf_file == NULL)
{
perror("Can not open the file");
}
printf("size of struct %ld\n", sizeof(Buffer));
buffer->size = fread(&buffer->data, sizeof(char), BUFFER_SIZE, pdf_file);
fclose(pdf_file);
sem_post(&task1);
sem_wait(&task2);
printf("A is out\n");
return NULL;
}
void *thread_B(void *arg)
{
printf("IAM IN TREAD B");
Buffer *buffer = (Buffer*) arg;
sem_wait(&task1);
int i=0;;
int byte_counts[256] = {0};
while (buffer->size != i) {
unsigned char byte = buffer->data[i];
byte_counts[byte]++;
i++;
}
for (int i = 0; i < 256; i++)
{
printf("Byte-value %02X: %d\n", i, byte_counts[i]);
}
sem_post(&task2);
printf("threadB is done 2\n");
return NULL;
}
memory is a pointer to a Buffer (Buffer *), and by taking its address, you get a pointer to a pointer to a buffer (Buffer **):
Buffer *memory = malloc(sizeof(Buffer));
...
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
But in the thread functions, you're assuming that arg is a Buffer *:
Buffer *buffer = (Buffer*) arg;
This causes undefined behaviour.
Clearly there's one indirection too many; memory is already a pointer so we don't need to take its address:
pthread_create(&thread_A_id, NULL, &thread_A, memory);
pthread_create(&thread_B_id, NULL, &thread_B, memory);
If file fails to open, fread will return -1 and it's not checked. So the loop in thread_B will read first garbage from buffer->data and then will continue out of limit (because of comparison with -1).
So, at first, there is missing handling of error from fopen() - thread_a continues after perror, second - missing error check after fread().
By the way, the check for
if (buffer->size == i)
after while (buffer->size != i) is superfluous :)
Need some help as I unable to perform pthread_join operation.
I have a thread handle which has been created dynamically
void *threadHandle;
threadHandle = (pthread_t*)malloc(sizeof(pthread_t));
I cannot create handle by value.
The thread is getting created successfully.
However, when I am trying to do pthread_join, I am getting segmentation fault.
pthread_join takes handle which has been created by value.
Is there any way I could do this operation ?
Edit:
Adding both the functions which are responsible for creating and joining the thread:
int care_thread_create(void *threadHandle, void *attr, void *(*start_routine)(void *), void *args)
{
printf("Thread Creation Started \n");
threadHandle = (pthread_t*)malloc(sizeof(pthread_t));
int returnValue = pthread_create(threadHandle, (pthread_attr_t *)attr, start_routine, args);
printf("Thread Creation Completed \n");
return returnValue;
}
int care_thread_join(void *threadHandle)
{
int returnValue = pthread_join(*(pthread_t*)threadHandle, NULL);
return returnValue;
}
You join it just like you would with a handle allocated automatically.
The signature of pthread_join is
int pthread_join(pthread_t thread, void **retval);
This means that if you have a pthread_t* you need to dereference that pointer to supply a pthread_t argument to pthread_join().
Example:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* threadfunc(void* vptr) {
puts("in thread");
return NULL;
}
int main() {
pthread_t *threadHandle; // Note: Use the proper type
threadHandle = malloc(sizeof *threadHandle);
if(threadHandle == NULL) return 1;
if(pthread_create(threadHandle, NULL, threadfunc, NULL) == 0) {
// ...
pthread_join(*threadHandle, NULL); // join by dereferencing threadHandle
}
free(threadHandle);
}
Demo
I'll extend this to address the issues I see with the functions you've added to the question.
You are using the wrong types! Don't use void*, use pthread_t* and pthread_attr_t*
Not only is it correct - it actually helps you to create the program since the compiler will complain if you use the wrong type. You actually do not need any casts for this.
A naive fix to that problem (warning - don't use this version):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* threadfunc(void* vptr) {
(void)vptr; // discard warnings about the unused variable
puts("in thread");
return NULL;
}
// note: you need a `pthread_t**` here:
int care_thread_create(pthread_t **threadHandle, pthread_attr_t *attr,
void *(*start_routine)(void *), void *args)
{
*threadHandle = malloc(sizeof(pthread_t));
int returnValue = pthread_create(*threadHandle, attr, start_routine, args);
return returnValue;
}
int care_thread_join(pthread_t *threadHandle)
{
int returnValue = pthread_join(*threadHandle, NULL);
free(threadHandle);
return returnValue;
}
int main() {
pthread_t *threadHandle; // Note: Use the proper type
if(care_thread_create(&threadHandle, NULL, threadfunc, NULL) == 0) {
// ...
care_thread_join(threadHandle);
}
}
The keen eye may see a problem here. What if starting the thread fails? Yes, the program will then leak the memory allocated in care_thread_create. Also, if memory allocation failed in care_thread_create, then you'd call pthread_create with a NULL pointer and get undefined behavior.
Here are possible fixes for that:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void* threadfunc(void* vptr) {
(void)vptr; // discard warnings about the unused variable
puts("in thread");
return NULL;
}
// don't pass in a pointer, just let the function allocate and return it to you
pthread_t *care_thread_create(pthread_attr_t *attr,
void *(*start_routine)(void *), void *args)
{
pthread_t *threadHandle = malloc(sizeof *threadHandle);
if(threadHandle == NULL) return NULL; // if allocation failed
if(pthread_create(threadHandle, attr, start_routine, args)) {
// if creating the thread failed, free the allocated memory
free(threadHandle);
return NULL; // and return NULL
}
return threadHandle; // success
}
int care_thread_join(pthread_t *threadHandle)
{
int returnValue = pthread_join(*threadHandle, NULL);
if(returnValue == 0) free(threadHandle);
return returnValue;
}
int main() {
// simpler interface for the user:
pthread_t *threadHandle = care_thread_create(NULL, threadfunc, NULL);
if(threadHandle) {
// memory allocated and thread successfully started
// ...
care_thread_join(threadHandle); // joins and free's
}
}
Demo
If you need to handle both Windows and Posix, you can hide the pthread_t* or HANDLE* in a struct to provide the user of the library type checking when developing.
mythread.h:
#pragma once
// this is defined in the common header for Windows and Posix:
typedef struct { void *thread; } mythread_t;
#define MYTHREAD_STARTED(x) ((x).thread != NULL)
And this would be the posix implementation part:
#include "mythread.h"
#include <pthread.h>
#include <stdlib.h>
mythread_t care_thread_create(void *attr,
void *(*start_routine)(void *), void *args)
{
mythread_t retval = {.thread = NULL};
pthread_t *pt = malloc(sizeof *pt);
if(pt == NULL) return retval; // if allocation failed
if(pthread_create(pt, attr, start_routine, args)) {
free(pt);
return retval;
}
// success, put the `pthread_t*` in the return value:
retval.thread = pt;
return retval;
}
int care_thread_join(mythread_t *threadHandle)
{
pthread_t *pt = threadHandle->thread;
int returnValue = pthread_join(*pt, NULL);
if(returnValue == 0) {
threadHandle->thread = NULL;
free(pt);
}
return returnValue;
}
Example usage:
int main() {
mythread_t threadHandle = care_thread_create(NULL, threadfunc, NULL);
if(MYTHREAD_STARTED(threadHandle)) {
// memory allocated and thread successfully started
// ...
care_thread_join(&threadHandle); // joins and free's
}
}
Demo
I'm very new in C and Linux and English is not my mother language. Sorry in advance.
I'm working on a school project which is implementing thread api and I made the thread_create() function using clone().
The problem is that when I call thread_create(&tid1, NULL, (void *)Testcase1, 0); ,
it creates a new thread but TestCase1 also includes thread_create and it doesn't seem create another thread. Let me explain with my code below:
int foo(void* arg){
printf("Hii");
return 0;
}
int thread_create(thread_t *thread, thread_attr_t *attr, void *(*start_routine) (void *), void *arg)
{
void* stack;
stack= malloc( STACK_SIZE );
pid_t pid;
if( stack==0)
{
perror( "malloc : could not allocate stack" );
exit( 1 );
}
pid = clone( &foo ,( char* )stack+STACK_SIZE,SIGCHLD|CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES,0 );
if(pid == -1)
{
perror("clone");
exit(2);
}
kill(pid, SIGSTOP);
Thread* newTCB = (Thread*)malloc(sizeof(Thread));
newTCB->stackSize = malloc(STACK_SIZE);
newTCB->pid = pid;
newTCB->status = THREAD_STATUS_READY;
rEnqueue(newTCB);
rPrintqueue();
free(stack);
printf("Child thread returned and stack freed.\n");
return 0;
}
And this is my test code below:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
TestCase1() below:
int Tc1ThreadProc(int param)
{
int tid = 0;
int count = 0;
tid = thread_self();
count = 3;
while (count > 0)
{
/* sleep for 1 seconds */
sleep(2);
printf("Tc1ThreadProc: my thread id (%d), arg is (%d)\n", tid, param);
count--;
}
}
void TestCase1(void)
{
thread_t tid[TOTAL_THREAD_NUM];
thread_create(&tid[0], NULL, (void*)Tc1ThreadProc, (int*)1);
thread_create(&tid[1], NULL, (void*)Tc1ThreadProc, (int*)2);
thread_create(&tid[2], NULL, (void*)Tc1ThreadProc, (int*)3);
while(1){}
return ;
}
it's supposed to print "Tc1ThreadProc: my thread id (%d), arg is (%d)\n" 3 times but it prints only "Hii" which is because of the call to foo().
How do I fix this?
You pass pointer to function "TestCase1" as argument to "thread_create", but inside "thread_create" you don't use it at all:
thread_create(&tid1, NULL, (void*)TestCase1, 0);
You're calling "clone" syscall only with pointer to "foo" function.
From inside "thread_create" your "TestCase1" pointer is named "start_routine", so you need to call similar "clone" syscall, but instead pointer to "foo" you should pass pointer to "TestCase1". Something like that:
pid = clone( start_routine, (char*) stack + STACK_SIZE, SIGCHLD | CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES, 0);
I am running 32 bits of OS.
Now the thread I created will return a int value which it could be larger than 4G.
How can I receive this value from my main() function by pthread_join()?
Looks like in 32 bits system, (void *) is 4 bytes.
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
void* thread_function(void)
{
uint64_t nbytes = 0;
//assign values to nbytes, it could be larger than 4G.
return (void *)nbytes;
}
int main()
{
pthread_t thread_id;
uint64_t nbytes;
pthread_create (&thread_id, NULL, &thread_function, NULL);
pthread_join(thread_id,(void**)&nbytes);
}
Like this:
void* thread_function(void *)
{
uint64_t nbytes = 0;
//assign values to nbytes, it could be larger than 4G.
void *retval = malloc (sizeof (nbytes));
memcpy (retval, &nbytes, sizeof (nbytes));
return retval;
}
int main()
{
pthread_t thread_id;
uint64_t nbytes;
pthread_create (&thread_id, NULL, &thread_function, NULL);
void *ret;
pthread_join(thread_id, &ret);
memcpy (nbytes, ret, sizeof (nbytes));
free (ret);
}
This is a common pattern for transferring a value from one thread to another. The sending thread allocates memory, copies in the value, and passes a pointer. The receiving thread gets the pointer, copies out the value and frees the pointer.
David Schwartz's solution is well known but a bit too much to pass a simple integer; malloc() is expensive and not necessarily thread safe(highly unlikely but with all of the embeded stuff today…).
Picking up the idea of the first two commenters to the OP (WhozCraig and Eugene Sh.)
#include <stdio.h>
#include <stdint.h>
#include <pthread.h>
#include <stdlib.h>
void *thread_function(void *arg)
{
/*
No direct dereferencing
*arg = 0xdeadbeefcafe;
would give a compile error. With GCC it would be
threadargs.c:8:5: warning: dereferencing ‘void *’ pointer [enabled by default]
*/
uint64_t *nbytes = arg;
*nbytes = 0xdeadbeefcafe;
// you can return a simple status here, for example an error
return 0;
}
int main()
{
pthread_t thread_id;
uint64_t nbytes;
pthread_create(&thread_id, NULL, &thread_function, &nbytes);
pthread_join(thread_id, NULL);
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
printf("nbytes = %" PRIx64 "\n", nbytes);
return 0;
}
Should do the job in another way, maybe a better one for this type of usage.
Disadvantage: every thread wants its own variable to fill, so it is a better fit for a fixed, small amount of threads, otherwise you are allocating from the heap and have won nothing, just the opposite: it would be more complicated to keep hold off all the malloc()/free(). David Schwartz's method would be much more apt in that case.
I want to run Pthreads in c. i am comfortable with sending integer values to Pthread in c. But when I am passing the data structure to the thread, it is printing garbage values.
My code is as follows:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMBER_OF_THREADS 3
typedef struct MyStructure
{
int id;
char *myName;
}myst;
void *PrintHello(void *threadArgs)
{
myst *myPersonalSt;
myPersonalSt = (myst *) threadArgs;
printf("Thread %d and Name : %s \n", myPersonalSt->id ,
myPersonalSt->myName);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUMBER_OF_THREADS];
long taskids[NUMBER_OF_THREADS];
int rc, t;
char myNameArray[NUMBER_OF_THREADS][100] = {"kp" , "kkp" , "ap"};
myst **mystArray;
mystArray = (myst **)malloc(NUMBER_OF_THREADS*sizeof(myst));
for(t=0;t<NUMBER_OF_THREADS;t++)
{
mystArray[t] = (myst *)calloc(1,sizeof(myst));
mystArray[t]->id = t+1;
mystArray[t]->myName = myNameArray[t];
}
for(t=0;t<NUMBER_OF_THREADS;t++) {
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
if (rc) {
printf("ERROR; return code from
pthread_create() is %d\n", rc);
exit(-1);
}
}
for(t=0;t<NUMBER_OF_THREADS;t++) {
pthread_join(threads[t],NULL);
}
pthread_exit(NULL); // this takes an input parameter !
}
I was thinking that it was a problem with MALLOC (because it doesn't initialize memory allocated). So I used CALLOC , but the same problem occured.
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
You're missing the array index here, you mean mystArray + t.
On a side note: remove all these casts, they make the code hard to read. void * is generic and implicitly convertible in c.
This line is wrong:
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) mystArray);
Given how you're written the rest of the code, it should be:
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) ( mystArray[t] ) );
But the use of malloc()/calloc() is unnecessary:
myst mystArray[ NUMBER_OF_THREADS ];
memset( mystArray, 0, sizeof( mystArray ) );
...
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) &( mystArray[t] ) );
That will work without the malloc()/calloc().