Cancel a thread within another thread - c

I have a multithreaded program. All I am doing in the main method is setting up multiple connections between clients and the server.
Each client runs this thread.
Now this thread has another thread within it.
What I want to do is close the connection at the end of the thread.
This is the code I am using. I have no idea why it does not work. Can anyone help me please?
void *thread_function(void * sock_desc){
//get the socket descriptor
int sock = *(int*)sock_desc;
int n;
int * sock2 = malloc(4);
*sock2 = sock;
pthread_t update_thread;
pthread_create(&update_thread, NULL, updater, (void*)sock2);
//do something
pthread_cancel(update_thread);
close(sock); //close the connection
free(sock_desc);
free(sock2);
return (void *)0;
}//close thread_function()

Related

write()/read() in a Client/Server, pthread application in C returns -1 always when on non-main thread?

So, I have this client/server application, where the server has a producer/consumer architecture. I have 2 functions that handle writting and reading to the socket. The main thread of the server (the Producer) handles connections and passes socket descriptors via a Stack to the second thread, the Consumer, for processing.
The problem is, whenever I try to write() or read() the socket from a different-than-main thread, it always returns -1 and causes a Connection reset by peer error on client and Transport endpoint is not connected error on the server. Surpirsingly, it works perfectly when socket is read/written from the main thread.
Why does this happen? Is this official behaviour? How do I go about replying to the client with the Consumer thread? I don't believe it's because of the code I wrote, since the Consumer thread only calls the read/write-to-socket functions.
If you have any suspicion on which part could be a culprit, ask me to post some of the code.
EDIT:
typedef struct s_stack {
int * c_stack;
int base;
int top;
unsigned char is_full;
unsigned char is_empty;
int max_size;
} s_stack_t;
s_stack_t stack;
void * producer_routine(void * arguments) {
/* socket(), bind(), listen(), etc.,
socket fd on "socket_fd",
new connection fd on "new_fd" */
for(;;) {
new_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &clen);
pthread_mutex_lock(&mutex);
while (stack.is_full) {
pthread_cond_wait(&stack_not_full, &mutex);
}
if (stack.is_full){
push(&stack, new_fd);
pthread_cond_signal(&stack_not_empty);
}
pthread_mutex_unlock(&mutex);
}
close(new_fd);
}
void * consumer_routine(void *args) {
for(;;) {
int socket_fd;
/* same mutex lock as above, just reversed, pop to socket_fd */
write_a_message_to_client(socket_fd);
}
}
int main() {
stack_init(&stack, 1024); // (s_stack_t * stack, int max_size)
pthread_t tidp, tidc;
int prc = pthread_create(&tidp, NULL, producer_routine, NULL);
int crc = pthread_create(&tidc, NULL, consumer_routine, NULL);
stack_destroy(&stack);
return 0;
}
The client just sends a message, and waits to receive one. If write_a_message_to_client() is called within any of those threads, even with the socket_fd passed as a parameter, I get the same errors. If it's called directly in main, it has no problem.
EDIT #2:
I tested this, and found my stack implementation to not work on Cygwin. Cygwin adds gibberish after the 3rd element for some reason, so the socket fds were invalid. Also, I was testing this in a Debian 6 VM and the server was crashing after connection from client. But I tested it in Arch, Kali and my Uni servers (Debian 7) and works as it should have been. A whole lot of trouble for a whole lot of nothing. Thanks Cygwin!
You should not call stack_destroy() until after both threads have completed. I think your entire program is running using a destroyed stack.
Use pthread_join() to wait for the threads to complete before destroying the stack.

Listening thread does not print statements

I am doing socket programming in C. In essence, I need a server that runs the indefinite listening loop in a separate thread and whenever it accepts a new connection, it must create a new client thread to handle the client's requests.
Below I have the main function that declares a port number and calls the function createListenThread. This function creates a new thread and invokes the function listenLoop.
int main(int argc, char *argv[])
{
int client_port = 6000;
createListenThread(client_port);
}
void createListenThread(int listen_port)
{
pthread_t listen_tid;
printf("In createListenThread\n");
// listenLoop(&listen_port);
if(pthread_create(&listen_tid, NULL, listenLoop, &listen_port) != 0)
socketError("Could not create thread\n");
}
void *listenLoop(void *arg)
{
pthread_detach(pthread_self());
int listen_socket, listen_port, *client_socket, struct_size;
struct sockaddr_in client_addr;
pthread_t client_tid;
listen_port = *((int *)arg);
listen_socket = createSocket(listen_port);
struct_size = sizeof(struct sockaddr_in);
while(1)
{
printf("In ListenLoop\n");
client_socket = malloc(sizeof(int));
*client_socket = -1;
*client_socket = accept(listen_socket, (struct sockaddr *)&client_addr, &struct_size);
printf("Received connection request from (%s , %d)\n",
inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
pthread_create(&client_tid, NULL, starterFunction, client_socket);
}
close(listen_socket);
}
My problem is that whenever I run the server, only "In ListenThread" and "In ListenLoop" is never printed. I have even tried fprintf(stdout, "In ListenLoop") and fflush(stdout) but the statement is still not printed. When I comment out:
if(pthread_create(&listen_tid, NULL, listenLoop, &listen_port) != 0)
socketError("Could not create thread\n");
and simply invoke ListenLoop as follows:
listenLoop(&listen_port);
Both the print statements appear. Is there an obvious mistake in the way I'm creating the thread and invoking the ListenLoop function? Is the function ListenLoop ever executed?
Edit: I ran the program in gdb which printed the following:
In createListenThread
[New Thread 0xb7e30b70 (LWP 10024)]
[Thread 0xb7e30b70 (LWP 10024) exited]
[Inferior 1 (process 10021) exited normally]
Why is the thread exiting??
The problem will be that your main function returns immediately after calling createListenThread. You should wait for your thread function to finish using pthread_join within your createListenThread otherwise the program may terminate before the thread function can finish. Calling pthread_join on your thread will wait until the thread function returns and will therefore definitely get chance to run before main() returns.
I hope that you declare all your functions above main ... But you should really call your listenLoop in main thread. Else, you create a thread to run the loop and main thread passively waits it. And you will not be bothered by argument passing, thread waiting and so on.
listenLoop could then be a true void and no longer a void *, as you do not return anything.
If you were forking a process, it would make sense, since it is the correct way to create a daemon process immediateley adopted by init process, but for threads it is simply useless.

Implementing thread in UDP server using c

I am trying to implement a multithreaded UDP server by creating thread.
The following method is used for creating thread.
pthread_create(&threadID, NULL, ThreadMain, threadArgs);
ThreadMain method is,
void *ThreadMain(void *threadArgs) {
pthread_detach(pthread_self());
int sock = ((struct ThreadArgs *) threadArgs)->sock;
free(threadArgs);
HandleUDPClient(sock);
return (NULL);
}
In the HandleUDPClient method is like this,
void HandleUDPClient(int sock) {
struct sockaddr_storage clntAddr; // Client address
// Set Length of client address structure (in-out parameter)
socklen_t clntAddrLen = sizeof(clntAddr);
// Block until receive message from a client
char buffer[MAXSTRINGLENGTH]; // I/O buffer
// Size of received message
ssize_t numBytesRcvd = recvfrom(sock, buffer, MAXSTRINGLENGTH, 0, (struct sockaddr *) &clntAddr, &clntAddrLen);
...
...
When I am creating socket and running the HandleUDPClient method it handles requests from client perfectly. But when I am trying to use thread, after entering the HandleUDPClient method it does not process the recvfrom method. Actually it does not wait for the client to receive any request. Program just terminates.
Can anybody tell me why this problem occurring and how can I resolve it?
The problem is that you detach your threads, meaning that you will not have to wait for your threads to exit. Instead the main program continues its work, until it reaches its end and then exit, with no regard for the (detached) threads still running.
Either don't detach the threads, and use pthread_join to "join" the threads, or use pthread_exit from the main thread to make sure it will wait for all detached threads to finish.

Concurrent TCP server using threads

I'm trying to create a concurrent TCP server which accepts multiple(N connections) where N is known.(e.g.N=8) So I'm trying to create a prethreaded TCP server.
.....
for(i=0;i<NUMBER_OF_CONNECTIONS;i++)
{
CreateThreads(i);
}
return 0;
}
//Create threads to handle the connection
void CreateThreads( int i )
{
pthread_create(&thread_tid[i], NULL, thread_function, (void *) i);
return;
}
void* thread_function(void *arg)
{
puts("In thread_function");
int client_soc,clilen;
struct sockaddr_in *clientaddr;
if( (clientaddr = malloc(addrlen)) == NULL)
printf("malloc Error\n");
printf("thread %d starting\n", (int) arg);
while(1)
{
clilen = sizeof(struct sockaddr_in);
pthread_mutex_lock(&mlock);
puts("Calling accept \n");
if ( (client_soc = accept(socket_desc, (struct sockaddr *)&clientaddr,(socklen_t*)&clilen)) < 0)
{
printf("accept error\n");
}
pthread_mutex_unlock(&mlock);
printf("Process Request...calling connection handler \n");
connection_handler(client_soc); /* process request */
close(client_soc);
}
}
//This will handle connection for each client
void *connection_handler(void *socket_desc)
{
//Receive and process.....
return 0;
}
In the above code threads are created and the thread_function() gets called but it doesn't work as expected. The program comes to an end after calling the thread_function() till then a few threads get created.
I actually want the "N" number of threads to get created and wait for clients to connect(using accept()). Once connected i want to receive/collect data (or) sending commands etc. That's the reason i have connection_handler() but i'm stuck before that.
Can any one pls try to correct the thread_function() function ? I'm kind of getting stuck here.Thanks.
UPDATE
The program is based on the
http://www.cse.fau.edu/~jie/research/publications/Publication_files/roussevwu.pdf
Look at section 3.2 for using lock and accept.
The program comes to an end after calling the thread_function()
The problem is that after you create the threads the main thread falls through and ends the program. You should call pthread_join.
There's a problem with your approach. In your code you lock mlock and then you accept(2). You are calling a blocking function in a critical section. This severely limits parallelism, thus defeating much of the purpose of the threads.
You could try an approach where the main thread accepts and dispatches the new sockets to threads.

Sockets and threads using C

I am new to both sockets and threads. I have this code:
listen(socket_fd, 20);
/* Looooop */
while (1) {
newsocket_fd = accept(socket_fd,
(struct sockaddr *) &client_addr,
&client_len);
if (newsocket_fd < 0) {
error("ERROR on accept");
}
pthread_t thread;
pthread_create(&thread, NULL, run_thread, (void *) newsocket_fd);
pthread_join(thread, NULL);
}
How can I start a new thread for each new connection, rather than for each request? These threads should be started when a new connection comes in, and these threads should then wait for requests, handle those requests, and finally return when the connection is closed. There should be one thread for each connection. Here is the code for run_thread:
void
*run_thread(void *ptr) {
char buffer[256];
bzero(buffer, 256);
int n;
n = read((int) ptr, buffer, 255);
if (n < 0) error("ERROR Reading from socket");
printf("%s\n\n**********\n\n", buffer);
/* Parse buffer and return result */
char *result;
{
/* First, determine command, 4 characters */
/* (much code) */
}
n = write((int) ptr, result, strlen(result));
if (n < 0) error("ERROR Writing to socket");
}
Can anyone help me? Thanks.
There is also a different critical error.
You cast the int to (void*). This does not make sense. Also, you can't pass the address directly since the variable could be changed on the next accept() call before the thread can copy the variable to its local stack. One way to write it would be something like this:
while (1) {
newsocket_fd = accept(socket_fd,
(struct sockaddr *) &client_addr,
&client_len);
if (newsocket_fd < 0) {
error("ERROR on accept");
}
pthread_t thread;
int *newsock = malloc(sizeof(int));
*newsock = newsocket_fd;
pthread_create(&thread, NULL, run_thread, newsock);
pthread_detach(thread);
}
With this approach, the thread will make sure to free() the newsock. E.g a simple
void *handler(void *thread_data) {
int fd = *(int *) thread_data;
free(thread_data);
....
}
Also, I assume pthread_detach() is okay, if the main program doesn't care about syncing up with the thread later with pthread_join().
You almost got it right. The problem is, however, that you are joining the thread right after creation, and pthread_join is actually a blocking call which is waiting for the thread to finish. It means that you will not be able to accept any more connections while that one thread is running. To solve this problem, you might want to use detached threads. You don't have to join detached threads. For this purpose, you have to create thread attributes using pthread_attr_init function and pass those attributes to pthread_create.
Be aware that if you have too many client connections, your application may run out of resources. So, in real world, you have to manage a pool of threads. But the best case scenario for TCP/IP server applications is to use asynchronous I/O. I do not know about C, but there is a very good library in C++ for asynchronous I/O application called boost::asio.
Vlad has good advice.
Also note that your newsocket_fd variable is being reused for each new connection in your accept loop, and then a pointer to it is passed to every worker thread. This will cause problems when you start having multiple clients connected at the same time.
EDIT: Ignore this comment, I misread the mistake you were making. Others have given proper corrections for your handling of newsocket_fd.

Resources