Scheduling pthreads in Round-robin method - c

I am working on a multi-threaded server application.The server accepts connections from multiple devices and assign each connection a thread.The thread is a looping thread i.e it uses a while loop which iterates until the client closes the connection.
Currently when multiple clients got connected to the server only single client is able to communicate i.e the data sent by a single device is received at the server side and updated in database the other devices remain connected to server but no data is received from them. what seems the reason to me (not sure only assuming) is that only a single thread remains executing and other threads don't get the turn to execute.
so I want to schedule threads in round robin so that each thread executes.How can I schedule threads in round robin
I got the following code on-line but it was not able to schedule the threads in round robin.
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
pthread_attr_setschedpolicy(&attr, SCHED_RR);
Here is my code which creates threads:
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,(socklen_t*)&clntSock);
if(connfd > 0){
conn_desc = connfd;
puts("Connection accepted");
if(pthread_create( &thr, &attr , connection_handler , (void*)&conn_desc) < 0){
perror("could not create thread");
}

Your problem is not related to the scheduler policy. You have a potential race condition in your code.
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
conn_desc = connfd;
pthread_create(&thr,&attr,connection_handler,(void*) &conn_desc);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = *(int *) ptr;
...
return (void *) 0;
}
The race is that the parent can fire a second thread before the first thread has been able to dereference ptr. Thus, two threads will use the same value for connfd.
To correct this, we need to slightly modify the calling sequence to a pass-by-value:
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
pthread_create(&thr,&attr,connection_handler,(void*) connfd);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = (int) ptr;
...
return (void *) 0;
}
Side note: It is guaranteed that an int can be passed inside a pointer in this manner, but for sticklers, see below.
// parent thread
while (1) {
listen(...);
connfd = accept(sock_desc, (struct sockaddr *)&echoClntAddr,
(socklen_t*) &clntSock);
ptr = malloc(sizeof(int));
*ptr = connfd;
pthread_create(&thr,&attr,connection_handler,(void*) ptr);
}
// child thread function
void *
connection_handler(void *ptr)
{
int fildes = *(int *) ptr;
free(ptr);
...
return (void *) 0;
}

Related

How to keep my main thread and p thread alive?

I have a main function which, has a while loop which is Keeping my program live , but when i call the another thread (which is required), my main thread exits or I have to suspend it by calling thread join, i don know if its my codes problem
I have a this function calling my thread
int start_sender_engine(void)
{
thread1_ret = pthread_create(&Send_thread_1, NULL, Sender_thread,(void*) message1);
//pthread_join(Send_thread_1, NULL);
return 0;
}
im calling this thread here ,
now my main thread is like this
int main (int argc, char *argv[])
{
start_sender_engine();
while(1)
{
data.CommandCode=33+cont[0];
data.DataSize=sizeof(cont);
data.Data=cont;
Enqueue_elements(queue_hndl, &data);
usleep(1000*1000);
}
deleteQueue(queue_hndl);
}
my dequeue function is located inside the thread
void *Sender_thread(void *msg_ptr) // Sender Engine
{
char *message;
message = (char *) msg_ptr;
printf("%s\n",message);
fflush(stdout);
/*
* Create a datagram socket on which to send.
*/
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
perror("opening datagram socket");
exit(1);
}
/*
* Initialize the group sockaddr structure with a
* group address of 225.1.1.1 and port 5555.
*/
memset((char *) &groupSock, 0, sizeof(groupSock));
groupSock.sin_family = AF_INET;
groupSock.sin_addr.s_addr = inet_addr("225.1.1.2");
groupSock.sin_port = htons(65533);
/*
* Disable loopback so you do not receive your own datagrams.
*/
{
char loopch=0;
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *)&loopch, sizeof(loopch)) < 0) {
perror("setting IP_MULTICAST_LOOP:");
close(sd);
exit(1);
}
}
/*
* Set local interface for outbound multicast datagrams.
* The IP address specified must be associated with a local,
* multicast-capable interface.
*/
localInterface.s_addr = inet_addr("192.168.1.10");
if (setsockopt(sd, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&localInterface,
sizeof(localInterface)) < 0) {
perror("setting local interface");
exit(1);
}
/*
* Send a message to the multicast group specified by the
* groupSock sockaddr structure.
*/
//// Queue ////////
queue_hndl = createQueue(1000, (sizeof(SenderData) + 5000) );
while(stop_nw_global!=1)
{
if(no_elements(queue_hndl)>0)
{
temp=Dequeue_elements(queue_hndl);
printf("CMD Code %d",temp->CommandCode);
printf("---Size %d",temp->DataSize);
int *testi = (int*)temp->Data;
printf("Sending- %d\n", testi[0]);
fflush(stdout);
send_packets(*temp,100);
}
else
{
usleep(1000*1000);
printf(".\n");
fflush(stdout);
}
}
return 0;
}
when i comment pthread join, i get a error message as
>>>>>>Sender_Engine_Started<<<<<<<
0 [main] nwudp 1647 cygwin_exception::open_stackdumpfile: Dumping stack trace to
nwudp.exe.stackdump
.
when i un comment pthread join, my thread(Sender_thread)works perfectly, but my while loop inside my main stops
how can i make both alive? or should i create another thread for main?
I have figured out the issue, my queue handle "queue_hndl" was being used in the mains while loop before it was initialized, it was getting initialized just before my thread starts , so i have changed it acquire handle before starting my thread and now it works

My client doesn't send correctly to server

I have problems with my code.
I have this client with posix queue. Is a posix queue comunication with a conc server.
The question is down.
mqd_t server;
mqd_t client;
struct request req; //char *name, int pos, int op...
struct reply rep; //int num, int ret...
struct mq_attr attr;
attr.mq_maxmsg = 1;
attr.mq_msgsize = sizeof(struct reply);
client = mq_open("/CLIENT", O_CREAT|O_RDONLY, 0700, &attr);
server = mq_open("/SERVER", O_WRONLY);
req.name = name;
req.op = 3;
mq_send (server, (const char *) &req, sizeof(struct req),0);
mq_receive(client, (char*)&rep, sizeof(struct reply), 0);
mq_close(server);
mq_close(client);
mq_unlink("/CLIENT");
And this server
struct db mydb[100]; //Struct with char*name....
for (int i = 0; i<100;i++){
strcpy(mydb[i].name,"");
mydb[i].vec =NULL;
mydb[i].size =0;
}
mqd_t server;
struct request mess;
struct mq_attr q_attr;
pthread_attr_t t_attr;
q_attr.mq_maxmsg = 10;
q_attr.mq_msgsize=sizeof(struct request);
server = mq_open ("/SERVER", O_CREAT|O_RDONLY, 0700, &q_attr);
if (server == -1){
perror("Er");
}
pthread_mutex_init (&mutex_msj, NULL);
pthread_cond_init (&cond_msj, NULL);
pthread_attr_init(&t_attr);
pthread_attr_setdetachstate(&t_attr, PTHREAD_CREATE_DETACHED);
while(1){
pthread_t thid;
mq_receive(server, (char*) &mess, sizeof(struct request), 0);
AND HERE IS THE PROBLEM. WHEN I PRINF MESS.OP I WOULD RECIVE "3". The number that I asigned the client. And when I do this, mess.op have 0, not 3.
pthread_create(&thid, &t_attr, (void*)func, &mess);
...
...
...
...
}
Thanks.
It would appear that you are calling pthread_create() with a local (or automatic) variable mess which is sometimes deallocated before the thread is actually started. You need to allocate mess on the heap and be very careful to free it at the appropriate time.
Also (void *) func doesn't look right because,
The correct type is void *(*)(void *)
and it would appear as if you were ignoring compilation warnings, or forcing them to disappear by randomly casting a pointer to the type the compiler suggested.

Segmentation fault in accept system call

I have the following code serving as main loop for a server that accepts incoming socket connections.
At the moment the macro OperationMode is defined as 1 so it will execute the pthread logic.
for (hit = 1 ;; hit++) {
printf("Got here\n\n");
length = sizeof(cli_addr);
/* block waiting for clients */
socketfd = accept(listenfd, (struct sockaddr *) &cli_addr, &length);
if (socketfd < 0)
printf("ERROR system call - accept error\n");
else
{
printf("Testing\n\n\n");
#ifdef OperationMode
pthread_t thread_id;
if(pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL))
{
perror("could not create thread");
return 1;
}
#else
pid = fork();
if(pid==0)
{
ftp(socketfd, hit);
}
else
{
close(socketfd);
kill(pid, SIGCHLD);
}
#endif
}
}
I'm able to create a thread for the first incoming socket connection but once I iterate over the loop I get segmentation fault error in the line
socketfd = accept(listened, (struct sockaddr *) &cli_addr, &length);
My attendFTP function has the following code
void *attendFTP(int fd, int hit)
{
ftp(fd, hit);
return NULL;
}
This works perfect for the fork implementation. How can I fix the segmentation fault error?
pthread_create(&thread_id, NULL, attendFTP(socketfd, hit), NULL);
This code passess result of a call to attendFTP() with given paramters - and this result is always NULL.
So pthread_create is trying to launch a function at NULL address and, correspondingly, fails.
If you run your compiler with -pedantic argument, compiler will tell you that what you are doing is wrong. Without -pedantic, gcc allows for some 'extensions', which might hide errors. Btw, this is why -pedantic is, in my view, a must.
What you actually want is to pass some arguments to your threading function. Unfortunately, it is really convoluted in C pthreads, and requires you to allocate and deallocate the said struct. Something like this:
struct args {
int fd;
int hit;
};
...
pthread_t thread_id;
struct args* args = malloc(sizeof(struct args));
args->fd = socketfd;
args->hit = hit;
if(pthread_create(&thread_id, NULL, attendFTP, args))
....
void* attendFTP(void* vargs)
{
struct args* args = vargs;
ftp(args->fd, args->hit);
free(args);
return NULL;
}

C Socket Programming: reopen and reconnect socket [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
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.
Closed 7 years ago.
Improve this question
I am testing out my code for reconnection in case the connection drop. However I'm facing some Segmentation Error after the socket is re-opened and re-connected.
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h> //socket
#include <bluetooth/bluetooth.h> //bluetooth
#include <bluetooth/rfcomm.h> //bluetooth
#include <string.h> //strlen
#include <arpa/inet.h> //inet_addr
struct BTConnection {
int client;
int s;
int retry;
};
struct BTConnection bt_1;
void *bt_connect(void *arg);
void *bt_send(void *arg);
void *bt_receive(void *arg);
void *bt_connect(void *arg)
{
struct BTConnection *connect = (struct BTConnection*)arg;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
socklen_t opt = sizeof(rem_addr);
// allocate socket
connect->s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
// bind socket to port 1 of the first available
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 1;
bind(connect->s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(connect->s, 1);
// accept one connection
connect->client = accept(connect->s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
return 0;
}
void *bt_send(void *arg)
{
struct BTConnection *connect = (struct BTConnection*)arg;
char buf[1024] = { 0 };
int bytes_read, retry;
puts("[Bluetooth] Sending data to device...");
while(1) {
.....
pthread_mutex_lock(&mDataMutex);
puts("send mutex in");
while(connect->retry != 0);
puts("send mutex out");
pthread_mutex_unlock(&mDataMutex);
if(write(connect->client, return_msg, strlen(return_msg)) < 0) {
....
puts("Error reading from socket");
pthread_mutex_lock(&mDataMutex);
puts("send mutex");
if(connect->retry == 0)
connect->retry = 2;
pthread_mutex_unlock(&mDataMutex);
puts("send mutex end");
pthread_mutex_lock(&mDataMutex);
if(connect->retry == 2) {
close(connect->client);
close(connect->s);
bt_connect(&connect);
connect->retry = 0;
puts("send retry success");
} else
retry = 1;
pthread_mutex_unlock(&mDataMutex);
if(retry == 1)
{
puts("bluetooth send retrying in 8 secs");
sleep(8);
}
} else
retry = 0;
// clear buffer
memset(return_msg,0,sizeof return_msg);
memset(temp,0,sizeof temp);
// set to send data every second
sleep(1);
}
return 0;
}
void *bt_receive(void *arg)
{
// similar as above
}
int main(void)
{
bt_1.retry = 0;
int rc;
void *status;
pthread_t bt_connect_thread, bt_send_thread, bt_receive_thread;
pthread_attr_t attr;
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Create BT connect thread and start it
rc = pthread_create(&bt_connect_thread, &attr, bt_connect, (void *)&bt_1);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
return (-1);
}
rc = pthread_join(bt_connect_thread, &status);
rc = pthread_create(&bt_send_thread, &attr, bt_send, (void *)&bt_1);
rc = pthread_create(&bt_receive_thread, &attr, bt_receive, (void *)&bt_1);
rc = pthread_join(bt_send_thread, &status);
rc = pthread_join(bt_receive_thread, &status);
close(bt_1.client);
close(bt_1.s);
pthread_attr_destroy(&attr);
return 0;
}
The code may look a little messy in sending and receiving part as I was using mutex to check and debug the output.
This is the output I am getting:
[Bluetooth] Allocating socket... Done!
[Bluetooth] Bind socket... Done!
[Bluetooth] Waiting for incoming connections...
[Bluetooth] Accepted connection from 44:6D:6C:6D:1B:BC
[Bluetooth] Bluetooth connection thread completed
[Bluetooth] Receiving data from device...
rcv mutex in
rcv mutex out
[Bluetooth] Sending data to device...
send mutex in
send mutex out
send mutex in
send mutex out
[Bluetooth-Receive] Error reading from socket
receive mutex
receive mutex end
[Bluetooth-Receive] Connections closed. Reconnecting...
[Bluetooth] Allocating socket... Done!
[Bluetooth] Bind socket... Done!
[Bluetooth] Waiting for incoming connections...
[Bluetooth] Accepted connection from 44:6D:6C:6D:1B:BC
[Bluetooth] Bluetooth connection thread completed
Segmentation fault
I am not sure what is wrong since I did ensure that i close the socket before re-opening it. Any help/guidance? Thanks!
Edit: Not sure if bt_send is jamming it since it didn't print out [Bluetooth-Send] Error reading from socket when I'm sending test data automatically every second... (and both send and receive are running simultaneously)
PS. New to C and Socket Programming
void *bt_connect(void *arg)
{
struct BTConnection *connect = (struct BTConnection*)arg;
Okay, so we need to call bt_connect passing it a pointer to a BTConnection.
struct BTConnection *connect = (struct BTConnection*)arg;
...
bt_connect(&connect);
Since connect is a pointer to a BTConnection, &connect is a pointer to a pointer. So why are we passing it to bt_connect?

Boss Worker Pthreads Web Server in C - Server crashes if more requests sent than number of threads

I'm writing a web server in C (which I suck with) using Pthreads (which I suck with even more) and I'm stuck at this point. The model for the server is boss-worker so the boss thread instantiates all worker threads at the beginning of the program. There is a global queue that stores the socket of the incoming connection(s). The boss thread is the one that adds all items (sockets) to the queue as the connections are accepted. All of the worker threads then wait for an item to be added to a global queue in order for them to take up the processing.
The server works fine as long as I connect to it less times than the number of worker threads that the server has. Because of that, I think that either something is wrong with my mutexes (maybe the signals are getting lost?) or the threads are being disabled after they run once (which would explain why if there are 8 threads, it can only parse the first 8 http requests).
Here is my global queue variable.
int queue[QUEUE_SIZE];
This is the main thread. It creates a queue struct (defined elsewhere) with methods enqueue, dequeue, empty, etc. When the server accepts a connection, it enqueues the socket that the incoming connection is on. The worker threads which were dispatched at the beginning are constantly checking this queue to see if any jobs have been added, and if there are jobs, then they dequeue the socket, connect to that port, and read/parse/write the incoming http request.
int main(int argc, char* argv[])
{
int hSocket, hServerSocket; /* handle to socket */
struct hostent* pHostInfo; /* holds info about a machine */
struct sockaddr_in Address; /* Internet socket address stuct */
int nAddressSize = sizeof(struct sockaddr_in);
int nHostPort;
int numThreads;
int i;
init(&head,&tail);
//**********************************************
//ALL OF THIS JUST SETS UP SERVER (ADDR STRUCT,PORT,HOST INFO, ETC)
if(argc < 3) {
printf("\nserver-usage port-num num-thread\n");
return 0;
}
else {
nHostPort=atoi(argv[1]);
numThreads=atoi(argv[2]);
}
printf("\nStarting server");
printf("\nMaking socket");
/* make a socket */
hServerSocket=socket(AF_INET,SOCK_STREAM,0);
if(hServerSocket == SOCKET_ERROR)
{
printf("\nCould not make a socket\n");
return 0;
}
/* fill address struct */
Address.sin_addr.s_addr = INADDR_ANY;
Address.sin_port = htons(nHostPort);
Address.sin_family = AF_INET;
printf("\nBinding to port %d\n",nHostPort);
/* bind to a port */
if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR) {
printf("\nCould not connect to host\n");
return 0;
}
/* get port number */
getsockname(hServerSocket, (struct sockaddr *) &Address,(socklen_t *)&nAddressSize);
printf("Opened socket as fd (%d) on port (%d) for stream i/o\n",hServerSocket, ntohs(Address.sin_port));
printf("Server\n\
sin_family = %d\n\
sin_addr.s_addr = %d\n\
sin_port = %d\n"
, Address.sin_family
, Address.sin_addr.s_addr
, ntohs(Address.sin_port)
);
//Up to this point is boring server set up stuff. I need help below this.
//**********************************************
//instantiate all threads
pthread_t tid[numThreads];
for(i = 0; i < numThreads; i++) {
pthread_create(&tid[i],NULL,worker,NULL);
}
printf("\nMaking a listen queue of %d elements",QUEUE_SIZE);
/* establish listen queue */
if(listen(hServerSocket,QUEUE_SIZE) == SOCKET_ERROR) {
printf("\nCould not listen\n");
return 0;
}
while(1) {
pthread_mutex_lock(&mtx);
printf("\nWaiting for a connection");
while(!empty(head,tail)) {
pthread_cond_wait (&cond2, &mtx);
}
/* get the connected socket */
hSocket = accept(hServerSocket,(struct sockaddr*)&Address,(socklen_t *)&nAddressSize);
printf("\nGot a connection");
enqueue(queue,&tail,hSocket);
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond); // wake worker thread
}
}
Here is the worker thread. This should be always running checking for new requests (by seeing if the queue is not empty). At the end of this method, it should be deferring back to the boss thread to wait for the next time it is needed.
void *worker(void *threadarg) {
pthread_mutex_lock(&mtx);
while(empty(head,tail)) {
pthread_cond_wait(&cond, &mtx);
}
int hSocket = dequeue(queue,&head);
unsigned nSendAmount, nRecvAmount;
char line[BUFFER_SIZE];
nRecvAmount = read(hSocket,line,sizeof line);
printf("\nReceived %s from client\n",line);
//***********************************************
//DO ALL HTTP PARSING (Removed for the sake of space; I can add it back if needed)
//***********************************************
nSendAmount = write(hSocket,allText,sizeof(allText));
if(nSendAmount != -1) {
totalBytesSent = totalBytesSent + nSendAmount;
}
printf("\nSending result: \"%s\" back to client\n",allText);
printf("\nClosing the socket");
/* close socket */
if(close(hSocket) == SOCKET_ERROR) {
printf("\nCould not close socket\n");
return 0;
}
pthread_mutex_unlock(&mtx);
pthread_cond_signal(&cond2);
}
Any help would be greatly appreciated. I can post more of the code if anyone needs it, just let me know. I'm not the best with OS stuff, especially in C, but I know the basics of mutexes, cond. variables, semaphores, etc. Like I said, I'll take all the help I can get. (Also, I'm not sure if I posted the code exactly right since this is my first question. Let me know if I should change the formatting at all to make it more readable.)
Thanks!
Time for a workers' revolution.
The work threads seem to be missing a while(true) loop. After the HTTP exchange and closing the socket, they should be looping back to wait on the queue for more sockets/requests.

Resources