Thread workers and epoll - c

I'm trying to implement a server that deals with many tcp connections, from 100 - 1000 connections/day based on the time of the day. after reading a lot about the c10k problem with thread per connection and using epoll only I decided to use both as a pool of threads and the main will act as a dispatcher, so each new connection will be assigned to a thread.
I have a number of questions that I can't find answers anywhere else.
Is the following thread safe? Do I need to lock before adding the new fd?
int main ()
{
while(i < number_threads)
{
pthread_create( &id , NULL , worker , (void*) epoll_fd[i]);
i++;
}
//is it ok to add the new_sock for the epoll_fd[i] so the thread can pick it up
int y = 0;
while(1) {
new_sock = accept(...);
if (epoll_ctl(epoll_fd[y], EPOLL_CTL_ADD, new_sock, &ev) < 0)
{
print error;
}
y++;
if (y == number_threads)
y = 0;
}
}
void *worker(void *epfd)
{
epoll_wait //start waiting for event
}

If you do this:
pthread_create( &id , NULL , worker , (void*) epoll_fd + i);
and in the thread function, this:
void *worker(void *vp_epfd) {
int *p_epfd = (int*) vp_epfd;
then it should work, and be thread-safe, assuming that you check for updates in *p_epfd in correct places.

Related

accept call blocking thread termination

I'm having trouble terminating my server in my multithreaded program (one server, multiple clients).
When the variable global_var, which counts the number of currently connected clients, gets set to 0, the server should terminate, but it doesn't.
What I think is happening is since accept() is blocking , the code never reaches the break condition in main loop.
It's breaking correctly out of thread_func but then it blocks inside the while loop, just before the accept() call and after printing "Exiting thread_func".
volatile int finished = 0; // Gets set to 1 by catching SIGINT/SIGSTOP
int global_var = 0; // When it gets to 0, server should terminate
int server_fd;
void * thread_func(void* arg)
{
do_some_pre_stuff();
while(1)
{
if(!global_var)
{
close(server_fd);
finished = 1;
break;
}
if(recv(...) > 0)
{
do_more_stuff()
}
else
{
disconnect_client();
global_var--;
break;
}
}
free_more_ressources();
return NULL;
}
int main()
{
do_initial_stuff();
init_socket();
listen();
while (!finished)
{
if( (fd = accept(server_fd,...)) == -1)
exit(-1);
global_var++;
/* Some intermediate code */
if(!global_var)
break;
// Thread for the newly connected player
if(pthread_create(&thread_id[...], NULL, thread_func, (void*)some_arg)
exit(-1);
}
free_resources();
puts("Exiting thread_func");
}
I tried the advice listed here without success (except the pipe answer, not trying to mess with pipes).
I'm new to socket programming but what I tried so far looked correct but none of the solutions worked (including semaphores, pthread_cancel,etc)
PS: synchronization has been implemented, just omitted here for readability

can pthread_join be unblockant?

i have a function like this :
void create_serv_and_init_client(client_t *cl, serv_t *serv)
{
static int i = 0;
pthread_t thread_serv;
if (i == 0) {
*serv = create_serv_socket();
if (pthread_create(&thread_serv, NULL, waiting_connection, \
(void *)serv) < 0) {
perror("could not create thread");
exit(1);
}
pthread_join(thread_serv, NULL);
cl[0] = create_client(0);
printf("OK\n");
i++;
}
}
waiting_connection function :
void *waiting_connection(void *server)
{
serv_t *serv = (serv_t *)server;
serv->newSocket = accept(serv->sockfd, (struct sockaddr*)&serv->newAddr, \
&serv->addr_size);
if (serv->newSocket < 0) {
exit(1);
}
if ((serv->childpid = fork()) == 0) {
close(serv->sockfd);
while (recv(serv->newSocket, serv->buffer, 1024, 0) != 0) {
printf("Client: %s\n", serv->buffer);
send(serv->newSocket, serv->buffer, strlen(serv->buffer), 0);
bzero(serv->buffer, sizeof(serv->buffer));
}
}
}
if i dont pthread_join, i will never receive the sended msg by the client, but however, it will block my program until receiving the message, but i wanna have a unblockant waiting of the client message, so it is possible to do a unblockant waiting, for the reception of the client message ?
because this is a game, so the server is launched when the first client is connected to the game, and if my program always wait others input of others plays, the actual players connected can't play, so this need to be unblockant, asynchronous if you want.
So you want one thread per client connection, and to be able to always accept a new client connection. That's sounds about right.
In that case the management of the messages received from a given client must be done in the corresponding thread, not in the main thread. The main thread only manages the client connections and launch the new threads, it does not have to join the other threads.
So the accept are done in the main thread, not in the separated threads, and it gives the socket with the new client in argument when it launch the new thread for that client, then pthread_detach the new thread.
if ((serv->childpid = fork()) == 0) {
close(serv->sockfd);
all of that does not exist, there is no fork, you use threads.
Of course an other way is to not use threads at all but to fork, anyway the roles are unchanged between the initial process and the child processes.
Your problem is that you didn't assign the right roles to everyone.

Joining two pthreads via pthread_join() doesn't work as expected [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I'm creating two different pthreads via pthread_create() and wait for them to exit by calling pthread_join().
When I run the program, the last output is "Waiting for thread1 to finish...", so it actually stops when trying to join the first thread and then terminates.
When I only create and run one thread and wait for its execution to be finished by using pthread_join(), everything works fine and the output is as expected.
What am I missing here? I already searched the web and figured out that pthread_join() doesn't behave as usual when creating more than one thread. But how do I actually use it in order to wait for finishing the execution of two pthreads?
Here's my code:
typedef struct
{
double speed_in_kmh;
double current_power_in_mega_watts;
} DeLorean;
typedef struct
{
unsigned int* cap_indices;
unsigned int array_length;
} IndexContainer;
typedef struct {
unsigned char* c_string;
unsigned int value;
} FluxCapacitor;
DeLorean* delorean__;
FluxCapacitor** capacitors__;
pthread_mutex_t lock;
// Thread function.
void* assembleDeLorean(void* indices)
{
// Get mutex to lock function and make sure
// that only one thread at a time is using it.
pthread_mutex_lock(&lock);
// Declare "indices" parameter as IndexContainer.
IndexContainer* iC = indices;
double sum = 0;
// Iterate through all given indices in iC
// and add value of iC to sum, if index exists.
for (int i = 0; i < 121; ++i)
{
for (int j = 0; j < iC->array_length; ++j)
{
if (i == iC->cap_indices[j])
{
sum += capacitors__[i]->value;
break;
}
}
}
// Assign computed sum to power of global delorean.
delorean__->current_power_in_mega_watts = sum;
// Release mutex.
pthread_mutex_unlock(&lock);
// Stop thread.
pthread_exit(NULL);
}
int main(void)
{
printf("Main thread \"main()\" was started.\n");
capacitors__ = createFluxCapacitorArray(121);
delorean__ = createDeLorean(0, 0);
IndexContainer* iC_1 = malloc(sizeof(*iC_1));
iC_1->array_length = 21;
iC_1->cap_indices = malloc(21 * sizeof(unsigned int));
IndexContainer* iC_2 = malloc(sizeof(*iC_2));
iC_2->array_length = 100;
iC_2->cap_indices = malloc(100 * sizeof(unsigned int));
// Fill iC_1.
for (int i = 0; i < 21; ++i)
{
iC_1->cap_indices[i] = i;
}
// Fill iC_2.
int k = 0;
for (int i = 21; i < 121; ++i)
{
iC_2->cap_indices[k] = i;
++k;
}
// Declare threads.
pthread_t thread1, thread2;
int rT1, rT2;
// Initialize mutex protecting "assembleDeLorean" function.
pthread_mutex_init(&lock, NULL);
// Create & run first thread.
printf("Creating and running thread1.\n");
rT1 = pthread_create(&thread1, NULL, assembleDeLorean, &iC_1);
if (rT1 != 0)
{
printf("Thread 1 could not be created.\n");
return EXIT_FAILURE;
}
printf("Return value of creation of thread1: %d\n", rT1);
// Create & run second thread.
printf("Creating and running thread2.\n");
rT2 = pthread_create(&thread2, NULL, assembleDeLorean, &iC_2);
if (rT2 != 0)
{
printf("Thread 2 could not be created.\n");
return EXIT_FAILURE;
}
printf("Return value of creation of thread2: %d\n", rT2);
// Wait for threads to finish.
printf("Waiting for thread1 to finish...\n");
if (pthread_join(thread1, NULL))
{
printf("An error occured while joining thread1.\n");
return EXIT_FAILURE;
}
printf("Thread1 finished!");
printf("Waiting for thread2 to finish...\n");
if (pthread_join(thread2, NULL))
{
printf("An error occured while joining thread2.\n");
return EXIT_FAILURE;
}
printf("Thread2 finished!");
return EXIT_SUCCESS;
}
You're passing incorrect arguments to your pthread_create() functions.
rT2 = pthread_create(&thread2, NULL, assembleDeLorean, &iC_2);
rT1 = pthread_create(&thread1, NULL, assembleDeLorean, &iC_1);
should be
rT2 = pthread_create(&thread2, NULL, assembleDeLorean, iC_2);
rT1 = pthread_create(&thread1, NULL, assembleDeLorean, iC_1);

When creating threads, some are getting a thread ID 0

I have a server application that creates new thread for every incoming request.
However, every once in a while, it will create a thread with thread ID = 0 (used pthread_equal to check this). I have a structure that contains the thread ID that I pass to the function specified in pthread_create, and am checking this there.
Why would a thread get created with ID = 0?
Is there anything I can do if this happens? I cannot use this thread and want to exit it immediately.
=====================================================================
typedef struct
{
pthread_t tid;
other_struct_t Other;
} data_ptr_t;
void * worker(void * arg)
{
data_ptr_t local_data;
data_ptr_t * incoming_data = (data_ptr_t *) arg;
if (NULL == incoming_data || NULL == incoming_data->Other)
{
printf("invalid input\n");
}
else if (pthread_equal(incoming_data->tid, 0))
{
printf("invalid thread id\n");
}
else
{
// add to global thread pool
// do other stuff here
// remove from global thread pool
}
}
int main()
{
// server socket stuff
while (1)
{
// if incoming connection is valid
data_ptr_t data;
int error = pthread_create(&(data.tid), NULL, (void * (*) (void *)) worker, (void *) &data);
if (0 != errror)
{
printf("could not create thread (%d)\n", error);
}
else
{
pthread_detach(data.tid);
printf("thread dispatched\n");
}
}
}
Note: If the number of threads I'm creating is under 50 or so, it works fine. Upwards of 70, most threads go through just fine, the rest end up printing the "invalid thread id".
Note: This is on Linux.
You can't do this:
while (1)
{
// if incoming connection is valid
data_ptr_t data;
int error = pthread_create(&(data.tid),
NULL, (void * (*) (void *)) worker, (void *) &data);
your data_ptr_t is a local variable on the stack. On the next iteration of the while loop, that variable is destroyed/gone/not-valid.
The while loop might start another iteration long before the new worker thread starts running and makes use of the data you pass to it. Instead, dynamically allocate the data you pass to the worker thread so you can be sure it's still valid.

Glib: how to start a new thread until another thread is finished?

I am using Glib to develop a multi-threading C software.
I would like to have a set of alive threads. Once some thread finishes, another thread starts with a different parameter. It is something like a thread pool.
I am using glib thread to implement the multi-threading. But I cannot find a lot of tutorials from Google. I can now start a set of threads, but have no idea about the waiting. Some code of mine:
GThread *threads[n_threads];
thread_aux_t *data = (thread_aux_t*) calloc(n_threads, sizeof(thread_aux_t));
for (i = 0; i < n_threads; ++i) {
data[i].parameter = i;
threads[i] = g_thread_create((GThreadFunc) pe_lib_thread, data + i,
TRUE, NULL);
}
/* wait for threads to finish */
for (i = 0; i < n_threads; ++i) {
g_thread_join(threads[i]); // How to start a new thread depending on the return value?
}
free(data);
Thanks.
Problem solved. Update:
Just found a thread pool implementation of glib: Thread Pools. I have run it and it works correctly.
The code is written as:
// 'query' is for this new thread,
// 'data' is the global parameters set when initiating the pool
void *pe_lib_thread(gpointer query, gpointer data) {
}
void run_threads() {
GThreadPool *thread_pool = NULL;
// Global parameters by all threads.
thread_aux_t *data = (thread_aux_t*) calloc(1, sizeof(thread_aux_t));
data->shared_hash_table = get_hash_table();
g_thread_init(NULL);
thread_pool = g_thread_pool_new((GFunc) pe_lib_thread, data, n_threads,
TRUE, NULL);
// If n_threads is 10, there are maximum 10 threads running, others are waiting.
for (i = 0; i < n_queries; i++) {
query = &queries[i];
g_thread_pool_push(thread_pool, (gpointer) query, NULL);
}
g_thread_pool_free(thread_pool, 0, 1);
}
g_thread_join returns the return value, so you just check it.
Let's say you want to create a new process if the return value is 17.
for (i = 0; i < n_threads; ++i) {
if (threads[i] && g_thread_join(threads[i]) == 17) {
/* Start a new thread. */
threads[i] = g_thread_create((GThreadFunc) pe_lib_thread, data + i,
TRUE, NULL);
} else {
threads[i] = NULL;
}
}

Resources