pthread exit from thread in thread pool - c

I have a rather simple thread pool, and i have a question regarding thread finalizing.
this is my worker snippet :
static void* threadpool_worker(void* pool_instance)
{
int rc;
struct threadpool* pool = (struct threadpool*)pool_instance;
struct threadpool_task *task;
for(;;)
{
pthread_mutex_lock( &(pool->task_queue_mutex) );
while( pool->headp->tqh_first == NULL )
{
rc = pthread_cond_wait( &(pool->task_queue_cond), &(pool->task_queue_mutex) );
}
task = pool->headp->tqh_first;
TAILQ_REMOVE(pool->headp, pool->headp->tqh_first, entries);
pthread_mutex_unlock( &(pool->task_queue_mutex) );
task->routine_cb(task->data);
}
}
so jobs are executed at this line task->routine_cb(task->data);
and in order to finalize workers threads i'm calling threadpool_enqueue_task
in the following way :
for( i=0 ; i < pool->num_of_workers ; ++i)
{
threadpool_enqueue_task(pool, pthread_exit, NULL);
}
expecting that pthread_exit will be called in here task->routine_cb(task->data)
but it does not work this way, i don't see any explicit error, just memory leak in valgrind
but when i change the worker code like that :
if(task->routine_cb == pthread_exit)
{
pthread_exit(0);
}
task->routine_cb(task->data);
everything ends fine.
so my question is is there an option to stop the worker just making it to execute pthread_exit in some way,without changing the worker code.
Edit:
Thread pool task declared as following :
struct threadpool_task
{
void (*routine_cb)(void*);
void *data;
TAILQ_ENTRY(threadpool_task) entries; /* List. */
}
As per my understanig there should be no problem to get address of pthread_exit in routine_cb which declared :
extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));

I found the cause of the leak. It was my fault of course. I rewrote the job invocation in the following way :
void (*routine)(void*) = task->routine_cb;
void* data = task->data;
free(task);
routine(data);
instead of :
task->routine_cb(task->data);
free(task);
and there were no more leaks, and threads stopped as i expected.
Thanks to everyone who tried to help.

Related

Is it possible to create threads in multiple files to be executed in main file?

I have the following structure to want to interact with a sorter (infinite loop) and networker (infinite loop) on 2 separate threads. The threads are generated in each of their respective files instead of the main file. Are there any issues with this?
main.c
int main(void {
network();
sorter();
}
sort.c // creates random array then sorts them in a continuous while loop (never ending)
void sorter() {
int r1 = pthread_create(&thread1, NULL, (void *) &sorter, NULL);
pthread_join(thread1, NULL);
}
int* getArray() { ... }
int getElement() { ... }
network.c
void network() {
int r2 = pthread_create(&thread2, NULL, (void *) &startNetwork, NULL);
pthread_join(thread2, NULL);
}
void startNetwork() {
int sockfd, portno, optval, n;
socklen_t adSize;
struct sockaddr_in servAd, clientAd;
...
while(1) {
//receive packet
int *arr = getArray();
// send packets
// or receive packet that has a command to get array
}
}
Is it possible to have the threads structured like that? Will my main file freeze because the thread is not being created in the main file? Is there a better way to do this?
The main issues with sorter() are (1) that it won't return until the thread function returns, and (2) the thread function is sorter(), so you have an indefinite loop. This is likely a problem with trying to abstract your code into the question. There are nitty-gritty details to fix up like the types of the functions, etc.
The issues with network() might be similar or different; you've not shown the function you call from main(), so it is not clear what you intend. The code in networker() is not good; it makes pthread_create() call a function with an incorrect signature — thread functions should have the signature void *function(void *arg);.
However, in general, there is no problem with starting different threads in code from different source files. If the threads are not detached — if you're going to join them — then you'll need to make the pthread_t initialized by pthread_create() available for the code that manages the joining — possibly because they're in global variables or part of a global array, or possibly because you provide functional access to private data stored in the separate source files.
So, you might have:
network.c
static pthread_t thread2;
static void *network_thread(void *arg);
void network(void)
{
if (pthread_create(&thread2, NULL, network_thread, NULL) != 0)
…handle error…
}
void network_join(void)
{
void *vp = 0;
if (pthread_join(&thread2, &vp) != 0)
…report error…
…maybe use the return value in vp…
}
sorter.c
static pthread_t thread1;
static void *sorter_thread(void *arg);
void sorter(void)
{
if (pthread_create(&thread1, NULL, sorter_thread, NULL) != 0)
…handle error…
}
void sorter_join(void)
{
void *vp = 0;
if (pthread_join(&thread1, &vp) != 0)
…handle error…
…maybe use value in vp…
}
main.c
#include "sorter.h"
#include "network.h"
int main(void)
{
network();
sorter();
network_join();
sorter_join();
return 0;
}
You would probably build checks into network_join() and sorter_join() such that if you've not already called network() or sorter(), the code won't try to join an invalid thread.
Are there any issues with this?
It looks like maybe you do not understand what pthread_join(thread1) does. It does nothing, except wait until thread1 is finished. But you said that the network thread and the sorter thread are meant to run forever, so that's going to be a long wait:
For future reference, pthread_join() is meant to be used like this:
pthread_create(&thread1, attrs, f, arg);
doSomethingElse(...);
pthread_join(thread1, NULL);
doOtherStuff(...);
The original thread starts the new thread, and then it does something else while the new thread is calling f(arg). Then, after the f(arg) call and the doSomethingElse(...) call have both completed, the original thread goes on to doOtherStuff(...).

How to call a function when its pointer is stored in struct

How do i call the function in the following example.
i have a struct
struct Timing_Thread_Struct {
int SleepTime;
void (*Timing_Function)(int);
};
I have function where i fill the structure and create a thread
struct Timing_Thread_Struct timing_struct;
timing_struct.SleepTime = 30;
timing_struct.Timing_Function = ExampleFunction;
pthread_create(&delay_thread, NULL, Delay_Thread_Function, (void *)&timing_struct);
pthread_detach( delay_thread);
Example Function is
void ExampleFunction(int event) {
//Turn on a digital channel
}
Finally my Delay_Thread_Function
void *Delay_Thread_Function(void *arguments)
{
struct Timing_Thread_Struct *timing_struct = arguments;
msleep(timing_struct -> SleepTime );
//How do i call the function here?
pthread_exit(NULL);
return NULL;
}
How do i call the function stored in the struct?
i have tried
timing_struct->Timing_Function(1);
and it just crashes.
Thanks
Thread a creates struct Timing_Thread_Struct timing_struct; and fires up thread b, then returns, destroying timing_struct in the process. Thread b attempts to access timing_struct, which is destroyed, and gets garbage as a result. It is a common error to assume that timing_struct lasts for longer than the thread created below it.
This is likely remedied by using pthread_join to suspend execution of the calling thread.
As mention in other answers you are relying on the existence of the timing_struct variable but this might not be true.
If you are OK with pthread_join-ing the thread this should do e.g:
pthread_join(delay_thread, NULL); // instead of detach
See live example
Otherwise (if you have to detach) you should somehow guarantee the existence of the the struct e.g you could make a local copy and guard the process with a mutex and signal back using a conditional variable.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
bool created = false; // it's global just to make the example minimal
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct Timing_Thread_Struct {
int SleepTime;
void (*Timing_Function)(int);
};
void ExampleFunction(int event) { printf("Hi it's %d\n", event);}
void *Delay_Thread_Function(void *arguments)
{
pthread_mutex_lock(&mutex);
struct Timing_Thread_Struct timing_struct = *((struct Timing_Thread_Struct*)arguments);
created = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
// now this thread has it's own copy of the struct so the calling thread can end safely
timing_struct.Timing_Function(timing_struct.SleepTime);
pthread_exit(NULL);
return NULL;
}
int main(void){
struct Timing_Thread_Struct timing_struct;
pthread_t delay_thread;
timing_struct.SleepTime = 30;
timing_struct.Timing_Function = ExampleFunction;
pthread_create(&delay_thread, NULL, Delay_Thread_Function, (void *)&timing_struct);
pthread_detach(delay_thread);
pthread_mutex_lock(&mutex);
while(!created){
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
return 0;
}
Live example
I test your code and it did not crash, instead it just quit very quickly. So I think it is not the issue of function pointer in the struct. To confirm this yourself, try adding pthread_join(delay_thread, NULL); before calling pthread_detach and see whether it is still 'crash' or now working as your original intention.

Using a global variable to control a while loop in a separate thread

gcc (GCC) 4.6.3
c89
valgrind-3.6.1
Hello,
Updated code snippet
+++++++++++++++++++++++++++++++++++
void *thread_recv_fd()
{
pthread_mutex_lock(&mutex_queue);
while(start_receiving) {
pthread_mutex_unlock(&mutex_queue);
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
using the above locks looks very ugly now. And I am still getting a race error on the reading of the start_receiving. I have also declared it as volatile as well.
+++++++++++++++++++++++++++++++++++++
I am running a while loop in a worker thread that polls every 1/2 second. I control it with a global variable start_receiving after the user enters ctrl-c it will change the value to false.
Having a global like this is it good practice?
The reason I asked as I get these 2 errors when I run helgrind:
==6814== Possible data race during write of size 4 at 0x601958 by thread #1
==6814== at 0x401131: main (driver.c:78)
==6814== This conflicts with a previous read of size 4 by thread #2
==6814== at 0x4012A7: thread_recv_fd (driver.c:127)
This are the lines of code:
driver.c:78 is this line of code start_receiving = FALSE;
driver.c:127 is this line of code while(start_receiving) in the while loop
Source code, just the important snippets:
static int start_receiving = FALSE;
int main(void)
{
pthread_t thread_recv_id;
pthread_attr_t thread_attr;
/* Start polling as soon as thread has been created */
start_receiving = TRUE;
do {
/* Start thread that will send a message */
if(pthread_create(&thread_recv_id, &thread_attr, thread_recv_fd, NULL) == -1) {
fprintf(stderr, "Failed to create thread, reason [ %s ]",
strerror(errno));
break;
}
}
while(0);
/* Wait for ctrl-c */
pause();
/* Stop polling - exit while loop */
start_receiving = FALSE;
/* Clean up threading properties */
pthread_join(thread_recv_id, NULL);
pthread_exit(NULL);
}
void *thread_recv_fd()
{
while(start_receiving) {
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
Many thanks for any suggestions,
No, it's very bad practice.
At the very least, the variable should be volatile to avoid being optimized out.
You should really look into using some real multi-thread primitives for this though, such as mutexes (to protect the shared state, so that the two threads aren't accessing it at the same time) and atomic variables (to make sure the state is thread-proof).
Polling isn't a right way.
I suggest you to read about conditional variables
You could use atomics, but the simplest solution here is just to use locking around the controlling variable. For example:
static int start_receiving = FALSE;
static pthread_mutex_t start_receiving_lock = PTHREAD_MUTEX_INITIALIZER;
int is_receiving(void)
{
int r;
pthread_mutex_lock(&start_receiving_lock);
r = start_receiving;
pthread_mutex_unlock(&start_receiving_lock);
return r;
}
Then in the thread function:
void *thread_recv_fd()
{
while(is_receiving()) {
pthread_mutex_lock(&mutex_queue);
queue_remove();
pthread_mutex_unlock(&mutex_queue);
usleep(500);
}
pthread_exit(NULL);
}
..and in the main function:
pthread_mutex_lock(&start_receiving_lock);
start_receiving = 1;
pthread_mutex_unlock(&start_receiving_lock);

How to detect early exit from pthread_create without blocking for too long?

I have a thread called mainloop
i.e.
int run_mainloop;
void* mainloop(void* param)
{
// local vars
// initialize local vars
while(run_mainloop)
{
// run mainloop
}
return 0;
}
The thread is kicked off from a function called client_open, i.e.
int client_open()
{
run_mainloop = 1;
return pthread_create(&thread, NULL, mainloop, NULL);
}
However, in mainloop if initializing local variables fails I need to inform client_open right away of early exit.
pthread_join is inappropriate as it will block and I can't have client_open block.
If it was to wait a short time before returning that would be ok.
How could I do this in a nice way without using pthread_join which will block.
I want to be able to get the return code.
Using pthread_tryjoin_np would be incorrect: the new thread could be arbitrarily delayed between pthread_create return, and the new thread actually executing initialization code.
If you pthread_tryjoin_np during that delay, the join will fail and you will decide that everything is "a-ok", when in fact it isn't.
What you want is a condition: client_open will await on it, and the mainloop will signal it (upon being done with initialization).
You can use something known as completion variables.
Using which a thread can wait till a newly created thread has finished initialization. The only catch is that the new thread must always signal its initialization completion, even when initialization fails.
Something along the following lines (error handling omitted for clarity):
#include <pthread.h>
// Completion variable definition:
typedef struct {
pthread_mutex_t mtx;
pthread_cond_t cnd;
int completed;
int return_code;
} Completion;
#define COMPLETION_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
int completion_wait(Completion* c) { // add timeout if necessary
pthread_mutex_lock(&c->mtx);
while(!c->completed)
pthread_cond_wait(&c->cnd, &c->mtx);
int return_code = c->return_code;
pthread_mutex_unlock(&c->mtx);
return return_code;
}
void completion_signal(Completion* c, int return_code) {
pthread_mutex_lock(&c->mtx);
c->completed = 1;
c->return_code = return_code;
pthread_cond_signal(&c->cnd);
pthread_mutex_unlock(&c->mtx);
}
// Usage:
void* mainloop(void* vc) {
int init_success = 0;
// initialization
// ...
init_success = 1;
init_end:
Completion* c = (Completion*)vc;
completion_signal(c, init_success); // always signal
if(!init_success)
return NULL;
// start the main loop
return NULL;
}
int client_open()
{
int run_mainloop = 1;
pthread_t thread;
Completion c = COMPLETION_INIT;
pthread_create(&thread, NULL, mainloop, &c);
pthread_detach(thread);
return completion_wait(&c);
}
Ok, I discovered three ways to do this.
1) Initialize and pass variables to mainloop before starting it.
2) Use the Linux specific pthread_tryjoin_np() or pthread_timedjoin_np()
I think the timed join version is more appropriate in this case as it allows time for the thread to be created and for initialisation to be done. The timeout need not be long so it will not block the caller to client_open() for very long.
However, as pointed out by #fge they are non-portable. While that isn't too much of a problem I thought about an alternative way which is this.
EDIT: Not such a good solution, but left in here for reference.
It'd be better to signal to open using a condition variable that initialization was ok.
3) Check if run_mainloop is non-zero, if it is and pthread_create didn't fail and the thread is running. If it's still zero after a time then it didn't start so we call pthread_join to get the exit code.
int run_mainloop = 0;
void* mainloop(void* param)
{
// init vars
// if failure, exit early.
// everything from this point on is good.
run_mainloop = 1;
while (run_mainloop))
{
// do styff
}
return 0;
}
int client_open()
{
void* res;
int rc = pthread_create(&g_thread_id, NULL, mainloop, NULL);
if (rc != 0)
return -1;
usleep(100); // wait a little while, kinda dumb but allows time for init
if (run_mainloop))
return 0;
pthread_join(g_thread_id, &res);
return -1;
}

Issue with threads: value stored in heap

I have an issue with threads.
I am defining a global variable, a char * that I initialize to NULL, and a mutex.
pthread_mutex_t mutex;
char *minURLTime;
minURLTime = NULL;
Then I initialize my mutex:
pthread_mutex_init(&mutex, NULL);
I then create a new thread:
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
And inside that function I allocate space for minURLTime using strdup and copy a string from link:
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
As I am using the heap (through strdup, which calls malloc), I do not understand why minURLTime is not NULL until the thread is exited, but then it is NULL.
pthread_exit(NULL);
Once pthread_exit is called, although minURLTime is a global variable that was allocated through strdup (which calls malloc), it appears to be NULL. I don't understand, could anyone please explain me?
Thank you very much,
EDIT:
A little more detail.
From main():
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
ExecuteThread function:
void *
executeThread( void *val )
{
executeRequest(*((int *) val));
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL AFTER THREAD ( BEFORE EXIT ): %s\n", minURLTime); // Not executed
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
fprintf does not get executed (BEFORE returning pthread_exit).
executeRequest Function:
void
executeRequest( int val )
{
/* some code */
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL: %s\n", minURLTime); // This one DOES print
pthread_mutex_unlock(&mutex);
}
}
This may be helpful. It prints inside executeRequest, but not inside executeThread, before the thread exited.
Jary
You aren't waiting in the main thread for the new thread to complete, so you're seeing the null before the thread gets around to setting something else. Also, since you haven't protected the variable with a lock, or declared it volatile, the compiler might even have optimized out noticing that the thread changed it.
My apologies, I realize what the problem was, it was something inside executeRequest that was messing up with those variables, I really don't know how it could have overwritten exactly THAT part of memory, but it is fixed. Thank you and sorry!

Resources