Client terminating on execution (pthread) - c

I have a socket programming problem. I am running the server and then it waits for the client. Once I run the client though, nothing happens, it just terminates and brings back the prompt. Basically it compiles alright but it doesn't run at all. It terminates as soon as I run it. This only happens when I use threads in the client code.
This is the code I'm using:
if(pthread_create(&threadID[i++], NULL, (void *)dostuff, (void *)(intptr_t)sock) != 0)
{
perror("Thread create error");
}
On the other hand, if I type in simply
dostuff(sock);
The client program does execute. I need threading because I need to implement I/O multiplexing. Could you tell me how to stop the client from terminating when I use threads?

You'll need to wait for the thread to finish before exiting the program, for example using pthread_join
// do this before returning from main
pthread_join(threadID[i], NULL);

Related

Problem with fgets in program using threads

i've been trying and searching to fix a problem in my program for several hours, and i haven't found any solution. My problem is the following: i have a program receiving queries to be executed, this program can take the queries as redirection or by input. When it's by input, the program needs to stop when user do CTRL+C or CTRL+D, before quitting the program, it needs to save the database. So i used fgets for reading queries to do something like:
void* queries_(void* prm){
while(fgets(buffer, 64, stdin)){..}
}
I used threads to speed up queries processing when we pass a file to the program by redirection. This is when i got a problem. I added threads to the main function calling this queries_processing function like this.
int main(int argc, char const *argv[]) {
signal(SIGINT, stop_);
pthread_create(&thread1, NULL, queries_, &db);
pthread_create(&thread2, NULL, queries_, &db);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// save database ...
}
But this is the part that i didn't understand, when user do CTRL+D, the while loop in queries_ stops for both threads and we get back to the main function and execute what is after the pthread_join. And for the ctrl+C, i created a function handler called stop_ where i fclose(stdin) to stop the while loop. But when i call this handler, the program get stuck, nothing happens, and the insturctions after the pthread_join isn't executed.
Any ideas what's causing that?
Do not call fgetc/fgets/fscanf on the same file handle (in this cases stdin) from multiple threads at the same time. Your program behavior is unspecified due to an unremovable race condition in the kernel.
Try using one thread to read from stdin and passing the line it read to the next available worker thread.

Running two independent threads in parallel in C socket

I am designing a C program for multi-threaded web server. I want to accept all the request on one thread and process them using threadpool on 2nd thread.
I am having hard time while making both the threads run parallel. I am attaching schema of my code.
pthread_t entry, scheduler, temp;
pthread_create(&entry, NULL, (void *)&listen, (void *)server_sockfd);
pthread_create(&scheduler, NULL, (void *)&scheduler, (void *)server_sockfd);
pthread_join (entry, NULL);
pthread_join (scheduler, NULL);
My 1st thread listen will accept all the request from client and put it in a queue and 2nd thread will schedule them.
My problem is: My first thread is running all the time and my 2nd thread never runs. 1st thread has socket function of accept() system call which is used in While loop so that it will listening all the time.
Please let me know how can I run both the threads in parallel.
Thank You.

multithread server doesn't continue to execute whenever a client get disconnected

hi there i'm working on a multithread Server (TCP) in C and i have a little issue about it. Everything works fine, more than one thread can connect to the server but whenever a client writes "exit" (which is a condition for a client when he/she writes "exit" string he/she goes to disconnect from the server) serves shutsdown itself also. So the communication through other threads get lost. However, logically it should be waiting for other clients even some current clients get disconnected. Here is a part of main and server is in a endless loop for waiting clients. hsock is id of socket belongs to server and csock is the id of clients.
main(){
.
.
.
while(1){
if(counter==0)
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (struct sockaddr*)&sadr, &addr_size))!= -1){
printf("---------------------\nReceived connection from %s\n",inet_ntoa(sadr.sin_addr));
pthread_create(&thread_id,0,&SocketHandler, (void*)csock );
counter++;
}
else{
fprintf(stderr, "Error accepting %d\n", errno);
}
}// end while
.
.
.
return 0
}
As you can see whenever a client get disconnected, server should keep waiting for an another threads. On the other hand, this is the last part of SocketHandler function which is a thread function.
void* SocketHandler(void* csock){
.
.
.
printf("Client disconnected\n");
free(csock);
return 0;
}
After return 0 statement isn't it necessary to return back to while(1) loop in main. I will be glad if you can help and thanks anyway
Threads run asynchronously once created, which means that the main thread (the one doing the accept) should continue looping and be back to accepting new connections, whatever the child thread does.
Some advices:
if your thread can run autonomously, use pthread_detach after the create to let thread handle its own termination graciously.
don't forget to do a close(csock) before ending the thread.
you don't necessarily need to allocate the int which will contain the socket descriptor, just pass it as the void * directly (but I guess that you will be passing more information than just the socket in a structure in a future version of your code).
After return 0 statement isn't it necessary to return back to while(1)
loop in main.
No. The thread exits. It has nothing to so with what happens in other threads.
I don't see how you can expect anybody to help you with a networking problem that happens on client disconnect when you don't show any code that handles the networking to the client.

Using signals and sigpipe

I'm working on an assignment that involves writing a program to process data (calculate pi) using fork (processes), signals and select.
I'm working right now on the signals and what I think I want to do is to use SIGPIPE so if the programs catches it, it tries to write to the pipe again (If a process tries to write to a pipe that has no reader, it will be sent the SIGPIPE).
I use fork() in main() to assign each process the same work by sending them to the worker function.
void worker(int id) {
.... (this piece of code is not relevant)
if(write(pfd[id][1], &c, sizeof(c)) == -1)
printf("Error occurred: %s\n",strerror(errno));
}
How can I implement signals in this function to catch SIGPIPE and make it write to the pipe again?
Thank you!
Typically, instead of catching SIGPIPE one ignores it, which causes write to fail with EPIPE instead of silently terminating your program.
However: If you are getting a SIGPIPE when you write to a pipe, then do not try again. It will never work. SIGPIPE means that the pipe has no reader -- and if the pipe has no reader now, it will never have a reader. (Think about it this way: how would a pipe with no reader get one? It is impossible!)
Your problem is that you are closing the other end of the pipe. Fix that, and don't worry about SIGPIPE. SIGPIPE is just the symptom.
Edit: There are two questions to answer here. If you can't answer both of these questions, then don't bother handling SIGPIPE.
What would cause my program to receive SIGPIPE? The only way to receieve SIGPIPE is for the reading end of the pipe to get closed. This happens if the reading process crashes, or if it is programmed to close the pipe. If you are writing a network server, or communicating with an unknown process, this might be common. However, if you write both programs, both run locally, then it probably indicates a programming error.
What would my program do when it catches SIGPIPE? If you are writing a client process that uses a pipe to communicate with a server, then what are you supposed to do with SIGPIPE? You can't try again, and clients usually can't restart the server they're connected to. Just do the sensible, default thing and let SIGPIPE terminate your program. However, if the server is sending data to a client it controls and gets SIGPIPE, it could restart the client. But this might be a very bad idea -- for example, if the client is deterministic, it will just crash again, and you will end up with an infinite loop rather than a simple crash.
So the general maxim here is "Only catch errors you are prepared to handle." Don't catch errors just for the sake of completeness. Just let them crash your program, or cause the operation to fail, and you can go back and debug it later.
Code snippet: This is a snippet of code from one of my projects. If you run it, SIGPIPE will not terminate your process. Instead, write will generate an EPIPE error. If you are writing a network server, then EPIPE is one possible way that a client might suddenly disconnect.
void
ignore_sigpipe(void)
{
struct sigaction act;
int r;
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
act.sa_flags = SA_RESTART;
r = sigaction(SIGPIPE, &act, NULL);
if (r)
err(1, "sigaction");
}

Creating a new thread (C, Windows)

OK, I'm a bit confused here. The following code works:
HANDLE CreateSideThread()
{
DWORD dwGenericThread;
HANDLE hThread1 = CreateThread(NULL, 0, CallBackFunc, NULL, 0, &dwGenericThread);
return hThread1;
}
int main()
{
HANDLE Thread1;
Thread1 = CreateSideThread();
WaitForSingleObject(hThread1, INFINITE);
SomeOtherFunction();
return 0;
}
The program does other things but you get the idea. It basically creates a new thread and executes whatever it is in CallBackFunc (which is an endless loop that check db status).
Now, if I remove WaitForSingleObject() then the program will not even try CallBackFunc once and execute SomeOtherFunction().
What's the point then of a thread? I mean, i'm confused here.
What I am trying to do is call that thread with the check for the database status and keep that thread going while I continue with my program, calling other functions.
What am I doing wrong?
Please post a sample snippet.
Thanks
Without the WaitForSingleObject, your call to SomeOtherFunction() probably returns quickly enough for the program to exit before the new thread even gets a chance to run once.
When a C program returns from its main() function, the runtime system calls exit() for you. This forcibly exits your program even if other threads are trying to run at the same time. This is in contrast to other languages like Java for example, where exiting the main thread will not exit the process until all other (non-daemon) threads have finished running too.
Threads are typically used for doing background work and freeing up the calling thread to do other things.
Normally, the behavior you describe (calling SomeOtherFunction()) is exactly what you'd want: I am going to kick of a background 'job' and go about my life.
It would appear that your example is just fine - though if you merely return from main() your thread will of course terminate (as it's owned by the parent process).
Maybe some more detail on why what you're doing isn't what you expect to happen?
What you're finding is that the main thread completes before you notice CallbackFunc is called. When you have the Wait call in, the main thread is blocked until the new thread finishes and so you see the thread func being executed.
Threads are not as cheap as you think, if you replace the SomeOtherFunction with something that takes a long enough time to run, you'll see your thread function being called even without the Wait call.
CallBackFunc will of course be called, but there is no guarantee, when your stared threads will be up and running. They will be working once, but its unpredictable when the start doing so. Thats the job and property of the systems scheduler. In your case they do not anything when the second function is already called.

Resources