What happens if more than one pthread uses a same function - c

I wonder what happens if two threads call the same function at the same time and the function is a UDP client that sends a text over the socket.
Considering the below code, I have been running it but I have not got any error yet. I wonder if it supposed to be crashed as the threads use the same source (function, variable, IP, port) at the same time, and how do they share the sources? I can imagine that the below code is a wrong usage of multi-threading, could you explain me how the threads should be used so that a thread would use the function only no other threads is using? In other word, how could it be thread-safe?
as an example C code on Linux:
void *thread1_fcn();
void *thread2_fcn();
void msg_send(char *message);
int main(void){
pthread_t thread1, thread2;
pthread_create( &thread1, NULL, thread1_fcn, NULL);
pthread_create( &thread2, NULL, thread2_fcn, NULL);
while(1){}
return 0;
}
void *thread1_fcn(){
while(1){
msg_send("hello");
usleep(500);
}
pthread_exit(NULL);
}
void *thread2_fcn(){
while(1){
msg_send("world");
usleep(500);
}
pthread_exit(NULL);
}
void msg_send(char message[]){
struct sockaddr_in si_other;
int s=0;
char SRV_IP[16] = "192.168.000.002";
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(12346);
si_other.sin_addr.s_addr = htonl(INADDR_ANY);
inet_aton(SRV_IP, &si_other.sin_addr);
sendto(s, message, 1000, 0, &si_other, sizeof(si_other));
close(s);
}

There isn't any problem with your code. Each thread, even if it runs the same code, has a separate stack, so a separate set of variables it works on. No variables are shared.

Since you create and close the socket inside msg_send, nothing special will happen. Everything will work fine.

Your code invokes undefined behavior because the threads pass small string literals as the message argument, but the function tries to send 1000 bytes starting at the message base address.
Since sendto is often a direct call to the operating system, either you will send a lot of garbage over UDP (or worse: security sensitive information!), or the system call will detect an out of bounds memory access and return -1 with errno set to something like EFAULT (likely without having sent any data).
Since message is a string, you should compute its length and then send only that amount (with or without the null terminator; that is up to you. The receiver can reconstruct a null terminated string from the length of the datagram.)
The function raises no concurrency issues, though.
The sendto function is safe even if multiple threads call it on the same socket. If you do that on a stream socket, though, you will likely run into problems with the data being interleaved into the byte stream in unpredictable ways.

Related

Is this C multithreaded tcp server correct?

I created a multithreaded C TCP server. It seems to work (as a client I type a message and the message is sent to the server and the server prints what the client sent in a thread (and send back the client id).
Do I respect the "best practices" of a C multithreaded TCP server ?
Maybe I should use a semaphore to access / use the client_counter variable ?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> // disable close() warning
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#define MAX_CONNECTIONS 5
static int client_counter = 0;
void* serverWorker(void* context)
{
char client_response[256];
int sock = *(int*)context;
char message[256] = "\n Hello dear client, you are the client number \n";
char numero[12];
sprintf(numero, "%d", client_counter); // SHOULD I USE A SEMAPHORE HERE FOR client_counter ?
while(1)
{
memset(client_response, 0, sizeof(client_response)); // clean string
recv(sock, &client_response, sizeof(client_response), 0);
printf("client number %s sent: '%s' \n", numero, client_response);
if (send(sock, numero , strlen(numero) , 0) < 0)
{
printf("ERROR while sending response to client from worker \n");
}
}
return NULL;
}
int main()
{
printf("Waiting for incoming connections ...\n");
// socket creation
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
// dserver address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
// bind the socket to IP and port
bind(server_socket, (struct sockaddr*) &server_address, sizeof(server_address));
listen(server_socket, MAX_CONNECTIONS);
int client_socket;
while((client_socket = accept(server_socket, NULL ,NULL)))
{
client_counter++;
pthread_t thread_id;
pthread_create(&thread_id, NULL, serverWorker, (void*)&client_socket);
printf("new client ! \n");
}
close(server_socket);
return 0;
}
There are several problems in your code... you create a thread on an incoming connection and pass all the created threads a reference (the same reference) to the variable in which you have stored the socket descriptor. This will make all threads to share the same variable to store all the socket descriptors you'll get from the wildcard one. Probably you think well, i make a copy just on thread start, so this is not going to happen, but think two connections that come in almost simultaneously, thread main() runs and processes both. Then the first and second threads get scheduled and both get the same descriptor stored (the second one) and the first connection is leaked.
Another thing is that while this variable is local to main, it will cease to exist as soon as main() returns (which is not the end of the program, if the threads are to survive past main()'s return) but as you are in an endless loop (you probably don't know, but the only means for the server_socket to give an error is if you destroy (close() it) in a thread, or you drop the interface it is attached to.) This could lead to a SIGSEGV trap.
You can freely pass an int value casted to (void *) without problem, as the thread body function will convert it back to an int before use, which reduces to a noop at all, as pointer types are normally greater in size (or equal, but not lesser) than int. Anyway, this is strictly undefined behaviour, but probably that will work (as legacy software is full of such conversions, so all compilers normally implement to try to respect this) The right way to do this is to declare a struct of information to be passed to the thread on start and return from it. Then you can store on it whatever you want, but think that, as you have a dynamic amount of threads to come, you need the structs to be dynamically allocated.
In respect to the use of the client_counter variable, the only thread touching that variable is the one running main() code. This plants no major problem than the risk presented above, two updates in quick sequence can make both threads to get the values updated in main after main has made both updates.
Another issue is that you need to declare it volatile as the thread code will not assume it is only changed by it between accesses and will probably cache it as a register variable.
The messages passed between main() and the different threads you are getting can be implemented in two ways. This is the reason of the routines to get a void * on input and returning a void * on return:
The first uses a dynamic struct of local data (malloc()ed, passed from main() to the thread, and back on termination, (when you join the thread to main). This way allows you to collect result info from the thread in main and then you have to free(3) the struct in main. The struct is used as a communication message between the thread and the main routine in both directions, and you can store there any information you need to pass or to return back. Once the thread has finished, you can free() the structure in main (don't do it in the thread, as it has to survive its death)
The second involves no more communication with main() and the threads must deallocate the structure, once it is finished. This is simpler, and more adequate to your example. In this way, you can destroy the struct in the thread, or in main, but only if you have already joined the thread and are sure the struct is not going to be used by it.
One common mistake is that you do not examine the return values of send and recv calls. These calls may send and receive less then the entire buffer and such cases must be handled, as well as disconnects. That will also remove the need to use memset and strlen on received data.
Generally, dedicating a thread to each client is considered non-scalable. You may like to read the famous The C10K problem for a good treatment of I/O strategies for handling many clients. The article is old but the advice is timeless.

c - socket failing when passed through pthread_create

I have a server that accepts clients. I'm doing some multi-threading, and when I create a thread, I pass the socketfd as an argument. The accept fails because the sockFd it takes is zero. However I can't figure out why this would be the case. The sockfd is valid for the take_client function, and it has been set up correctly. I just included this section of my code because I'm certain the issue is here.
void* thread_func(void* pSockfd) {
int sockFd;
sockFd = *(int*)pSockfd;
printf("sockFD = %d\n", sockFd); //returns zero
struct sockaddr_in sockAddr;
socklen_t sockAddrSize;
sockAddrSize = sizeof(struct sockaddr_in);
accept(sockFd, (struct sockaddr*) &sockAddr, &sockAddrSize);
return 0;
}
void take_client(int sock) { //when called, 'sock' is a valid number > 0
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
}
If anything stands out that might be an issue, I'd be really grateful to hear. Thanks!
there is a race condition in you code, it may look ok "sometimes":
void take_client(int sock) { //sock live on stack here
pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_func, (void*)&sock);
// you pass the stack address of sock to your thread
}
The address you pass must remain valid when thread is running, thus either you can afford that(it is kind of "global" somewhere), either you need to allocate a new buffer and pass it to the thread.
Sometime you will see code casting sock value to void* ( (void*)sock) and casting back the pointer to an int in the thread.
This may work, but I think allocating a new buffer is better for readability, and gives a clear ownership of who is responsible for this buffer (having a shared 'sock' between threads would need locking to be perfectly safe).
Moreover, usually, you end up with the need of passing many more info to the thread, thus already having a buffer ease the evolution of your code.
check out the man page for socket return value: "On success, a file descriptor for the new socket is returned. On error, -1 is returned, and errno is set appropriately." So a zero return value is valid. unless I didn't understand the issue you have.

Multithreaded sender

I am working on sending traffic (such as UDP/TCP packets) from one machine to another. I am writing a C application which has 1 thread for each traffic type. I want these two threads to concurrently send packets.
Do I need to use any synchronization primitives such as a mutex lock within the sendMsg function since it is being called from each thread?
sockaddr_in dest;
void * udp(void * arg){
struct * info = arg;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
//set up socket info
while(1){
sendMsg(udpInfo, fd);
}
}
void * tcp(void * arg){
struct * info = arg;
int fd = socket(AF_INET, SOCK_STREAM, 0);
// set up socket info
while(1){
sendMsg(tcpInfo, fd);
}
}
void sendMsg(struct * info, int fd){
sendTo(fd, "hello", strlen("hello") + 1, 0, (struct sockaddr*)&dest, sizeof(dest));
}
You seem to be a little unclear about how mutex works. A mutex is not applied on a piece of code, but a piece of data used within the code. Here the function is called by both threads, but there is no shared data between the threads. So as #Sami Kuhmonen said in a comment above, you don't need to use mutexes here.
You might need a mutex in future if, say, in case there was a third thread that pushed data into a (say) queue which your thread would then access from the queue and send to the connected computer. Then you would need to synchronise the way these threads push and pop data into and from the queue.
If you read the manpage for sendmsg you might see the following sentence:
If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
Atomically means that the package is always send in one blob with no other data being able to insert itself in the middle. So no matter how many threads use sendmsg the kernel will mix packets.

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.

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