trying to pass function pointer to pthread - c

I'm trying to create a pthread with arguments for a function pointer, here first is the function that will be called on pthread creation..
void *passenger(void *arguements){
struct arg_struct *args = arguements;
int passenger = args->p;
int from_floor = args->f;
int to_floor = args->t;
void (*enter)(int,int) = args->en;
void (*exit)(int,int) = args->ex;
// wait for the elevator to arrive at our origin floor, then get in
int waiting = 1;
while(waiting){
if(current_floor == from_floor && state == ELEVATOR_OPEN && occupancy==0) {
pthread_mutex_lock(&lock);
enter(passenger, 0);
occupancy++;
waiting=0;
pthread_mutex_unlock(&lock);
}
}
// wait for the elevator at our destination floor, then get out
int riding=1;
while(riding) {
if(current_floor == to_floor && state == ELEVATOR_OPEN){
pthread_mutex_lock(&lock);
exit(passenger, 0);
occupancy--;
riding=0;
pthread_barrier_wait(&barr);
pthread_mutex_unlock(&lock);
}
}
}
and here is the calling function
void passenger_request(int passenger, int from_floor, int to_floor,void (*enter)(int,int), void(*exit)(int,int))
{
pthread_mutex_lock(&passlock);
struct arg_struct args;
args.p = passenger;
args.f = from_floor;
args.t = to_floor;
args.en = *enter;
args.ex = *exit;
pthread_create(&thread, NULL, &passenger, &args);
//pthread_join(thread, NULL);
pthread_mutex_unlock(&passlock);
// wait for the elevator to arrive at our origin floor, then get in
}
The program is seg faulting when it creates multiple passengers on initilization, if I comment out the pthread_create line no crashing occurs. I'm assuming it's an issue with my passing of arguments for the function pointers, but I'm hazy as to what exactly is going on as all these pointers are starting to confuse me. Any help whatsoever would be much appreciated
also the struct declaration..
struct arg_struct{
int p;
int f;
int t;
void *(*ex)(int,int);
void *(*en)(int,int);
};

args.en = *enter;
args.ex = *exit;
enter and exit are function pointers. Don't dereference them but rather pass them straight through via args. That is, you need:
args.en = enter;
args.ex = exit;
(Assuming you have correct defined struct arg_struct which is not shown.

You are passing your new thread a pointer to args, which is defined on the stack of your passenger_request() function. As soon as passenger_request() returns, this memory could be reused, overwritten, or whatever. It is no longer guaranteed to contain what you put in it. Yet your thread still has a pointer to it and may continue to try to use it. This is likely to cause a crash, although it may be intermittent.
Try doing something different with args. If you only need it once, you could make it global. If you need multiple different ones, then allocate it on the heap with malloc:
void passenger_request(int passenger, int from_floor, int to_floor,void (*enter)(int,int), void(*exit)(int,int))
{
pthread_mutex_lock(&passlock);
struct arg_struct *args = malloc(sizeof(struct arg_struct));
args->p = passenger;
args->f = from_floor;
args->t = to_floor;
args->en = enter;
args->ex = exit;
pthread_create(&thread, NULL, &passenger, args);
//pthread_join(thread, NULL);
pthread_mutex_unlock(&passlock);
// wait for the elevator to arrive at our origin floor, then get in
}
Then in passenger() once you're well and truly done with it, free(args).

Related

Why can't I call function pointer from returned struct in C?

Ok so I've only been doing C a few weeks and I have some problems. I have a priority queue filled with Bsig pointers. As an added feature, I want that whenever a Bsig is popped, we execute a custom function.
typedef struct bsig{
// some more fields here, but they're not important
struct onpop_t *on_pop;
} Bsig;
typedef struct onpop_t {
struct onpop_t *next;
int (*do_on_pop)(Bsig *caller);
} Onpop;
int pop(SigPQ *q, Bsig* ret_sig){
if (q->size < 1){
return 0;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
ret_sig = signal;
return 1;
}
So essentially, whenever we call pop, the do_on_pop function should be launched. Furthermore, pop takes a signal pointer which is overwritten by whatever is popped from the queue. All this happens in two files included by main.c. The following is from main (where testpop is a custom function that juts prints something random - it is declared and defined in the main.c file):
Bsig *sig1 = new_signal(1000, 0);
Onpop *onpop1 = malloc(sizeof(Onpop));
onpop1->do_on_pop = &testpop;
sig1->on_pop = onpop1;
push(pq, sig1);
Bsig *ret_sig;
pop(pq,ret_sig);
So far so good - the custom function testpop gets called. But
ret_sig->on_pop->do_on_pop(ret_sig);
from main gives a segmentation fault! I don't understand why. The ret_sig address and the signal address should be the same, and the function call is the same - the only difference is that one is called from main and one is called from the included .c file. Can anyone shed a light?
You need to explicitly pass ret_sig by reference.
int pop(SigPQ *q, Bsig** ret_sig){
if (q->size < 1){
return 0;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
*ret_sig = signal;
return 1;
}
And pass the address of ret_sig
Bsig *ret_sig;
pop(pq,&ret_sig);
Or change the function to return the pointer instead of an int (which is cleaner):
Bsig *pop(SigPQ *q){
if (q->size < 1){
return NULL;
}
Bsig* signal = q->signals[0];
assert(signal);
q->signals[0] = q->signals[q->size-1];
q->size--;
sigpq_heapify(q,0);
if(signal->on_pop){
signal->on_pop->do_on_pop(signal);
}
return signal;
}
And assign the return value:
Bsig *ret_sig = pop(pq);

C - Reuse struct as argument for multiple PThreads

I have a while loop, and for each iteration of the loop, I am creating and populating a struct, and creating a thread while passing in that struct as an argument to the threaded function.
This is causing some issues - My while loop updates the data in the struct before my threaded function has a chance to make local copies of the struct data.
Does anyone know a good way to go about reusing a struct for multiple threads? I thought about using some kind of flag to make the main thread wait until the threaded function grabs its own copy, but this seems like it would introduce unnecessary waiting.
Here is an example of what I am trying to accomplish:
struct parameters {
int val1;
int val2;
int val3;
};
int main() {
...
while (readLine(file)) {
...
struct parameters *myParameters = malloc(sizeof(struct parameters));
myParameters.val1 = line.val1;
myParameters.val2 = line.val2;
myParameters.val3 = line.val3;
pthread_t myThread;
pthread_create(&myThread, NULL, &print, myParameters);
free(myParameters);
}
}
void *print(void *param) {
struct parameters *localParameters = param;
int threadVal1 = localParameters->val1;
int threadVal2 = localParameters->val2;
int threadVal3 = localParameters->val3;
}

How to pass a local struct as parameter to pthread_create?

The following function doesn't work. pin_thread_function sometimes receive garbage instead of the struct data. What is wrong? I know that is some basic scope related problem, but I can't explain.
typedef void (*state_callback_t)(int state);
struct pin_thread_params
{
char pin[3 + 1];
state_callback_t callback_onchange;
};
extern int pin_monitor_create(const char * pin,
state_callback_t callback_onchange)
{
int ret;
unsigned long int thread;
struct pin_thread_params params;
//Setup struct
strcpy(params.pin, "123");
params.callback_onchange = callback_onchange;
//Create thread with struc as parameter
ret = pthread_create(&thread, NULL, pin_thread_function, &params);
if (!ret)
{
ret = pthread_detach(thread);
}
return ret;
}
static void * pin_thread_function(void * context)
{
struct pin_thread_params params;
memcpy(&params, context, sizeof(params));
//Sometimes the correct string, most time garbage
printf("Started monitoring %s", params.pin);
}
When params is malloc'ed before pthread_create, everything works fine, like this:
...
struct pin_thread_params * params;
//Setup struct with malloc
params = malloc(sizeof(struct pin_thread_params));
strcpy(params->pin, "123");
params->callback_onchange = callback_onchange;
...
struct pin_thread_params params is statically allocated and the address of it is not safe to use once the scope of it is over (i.e. after pin_monitor_create has returned). It may happen that sometimes the thread execution starts before the pin_monitor_create has exited and you see the valid data in params. However, the dynamically allocated memory is from heap and will be usable until you free it, so you always get valid data in params within pin_thread_function .
I'm not particularly knowledgeable about pthreads (can't just comment quite yet), but you are passing a pointer to stack allocated memory to the thread which will eventually be clobbered by proceeding function calls.

Running `Function Pointers` Within Running `POSIX` Thread in `C` `Thread Pool`

I'm creating a threadpool in C with pthreads, and while I have an idea of how it works, I have a few questions about the intricacies.
I've created a struct which is supposed to be my representation of a threadpool, containing a list of function pointers to run, we'll call it the work_list. The threadpool struct also holds mutex's(?) and conditions to syncronize access, an int for the number of threads and an array holding the thread id's of each worked thread.The work_list itself holds structs that represent functions to be completed, each instance of those structs holds a void* to a function, a void* for args and a void* to place results. When coded this idea fleshes out like this:
typedef struct threadpool
{
list work_list;
pthread_t* tidArray;
int num_threads;
pthread_mutex_t lock;
pthread_cond_t condition;
} threadpool;
and:
typedef struct fuFunction
{
void* functionCall;
void* functionArgs;
void* returnValue;
list_elem elem;
} fuFunction;
I currently have a thread which initializes the a pool. It takes in a int num_of_threads, and returns a pointer to instance of a threadpool with all the members initialized. The body I've created looks like this:
threadpool * threadpool_init(int num_of_threads)
{
threadpool* retPool = (threadpool*) malloc(sizeof(threadpool));
//Initialize retPool members
int x;
for(x = 0; x < num_of_threads; x++)
{
pthread_t tid;
if( pthread_create(&tid, NULL, thread_start, retPool) != 0)
{
printf("Error creating worker thread\nExting\n");
exit(1);
}
retPool->tidArray[x] = tid;
}
return retPool;
}
The function that each thread runs when started, the worker function, thread_star, looks like this so far:
void *thread_start(void* args)
{
threadpool* argue = (threadpool*) args;
pthread_mutex_lock(&(argue->lock));
while(\* threadpool not shut down*\)
{
if(!list_empty(&argue->work_list))
{
fuFunction* tempFu = list_entry(list_pop_front(&argue->workQ), fuFunction, elem);
\\WHAT TO PUT HERE
}
pthread_cond_wait(&argue->condition, &argue->lock);
}
pthread_mutex_unlock(&(argue->lock));
}
My question is, assuming this code I currently have is right, how would I get the worker threads to run the function in the tempFu that it makes in the worker function? Sorry if this is long or confusing, I find this much easier to explain in conversation. If this is FUBAR, let me know as well.
the struct element signiture "void* functionCall;" is wrong.
use a function pointer instead.
Eg:
typedef struct fuFunction
{
void* (*functionCall)( void* arg);
void* functionArgs;
void* returnValue;
list_elem elem;
} fuFunction;
then put there:
tempfu->returnValue = (*tempfu->functionCall)(tempfu->functionArgs);

Call pthread_create from outside main function

I want to do something like this:
void *do_work_son(void *data)
{
mystruct *d = (mystruct*)data;
while(true)
{
// d->whatever is corrupt
}
}
void start_thread(pthread_t *mt)
{
mystruct data = ...;
pthread_create(&(*mt), NULL, do_work_son, (void *)&data);
}
int main()
{
pthread mt;
start_thread(&mt);
// do more stuff here
pthread_join(mt, NULL);
}
The idea is spawn off some threads and keep doing more work in main... then when done doing more work, wait for the threads to finish.
It compiles fine, but the data struct is corrupted when it gets accessed inside do_work_son. I think this is because the threads are exiting, even though I'm calling join in main. If I move the pthread_{create,join} calls both to start_thread, it works fine, but then my main function is blocked by the while loop. Am I crazy for doing it this way?
I think this is because the threads are exiting,
No, that's because data is an automatic variable in the start_thread() function, which is invalidated when start_thread() returns, so using its address afterwards invokes undefined behavior.
Either malloc()ate some memory for it, or make it static, or whatever. Just make sure it survives the death of start_thread().
The answer is simple: you are passing a reference of a local variable and then leaving the scope. Replace it with data allocated on heap and it would work like a charm
void start_thread(pthread_t *mt)
{
mystruct *data = malloc(sizeof(*data));
...;
pthread_create(mt, NULL, do_work_son, data);
}
EDIT:
About preassignment question:
void start_thread(pthread_t *mt)
{
mystruct local_data = {...};
mystruct *data = malloc(sizeof(*data));
*data = local_data;
...;
pthread_create(mt, NULL, do_work_son, data);
}

Resources