What signals it's better to handle in a TCP server? - c

I'm writing a TCP server.
Everything it has to do is to read/write text to/from TCP sockets and read/write this text to/from text files on the file system where the server runs.
If there's a problem with the connection (e.g. the client closes the socket), the server blocked on a read/write receives a SIGPIPE signal. I want to ignore it: the server simply closes its socket's end because the communication is now impossible.
Is it a good way?
Are there other signals I've to consider?

Many server programs choose to ignore SIGPIPE, and use the return codes from read/write to have better understanding of the disconnection. For example, read/recv returns 0 on a proper disconnect from the other end, and -1 on error with errno set to one of multiple alternatives.

You could also implement an interrupt handler, in case the server crashes you may want to do some operations before closing.
e.g. SIGINT
void interrupt_handler(int sig){
endloop = 1;
close(sd);
printf("Interrupt recieved: shutting down server!\n");
return;
}
int main(int argc, char** argv){
//all typical TCP socket functions
signal(SIGINT, interrupt_handler);
while(!endloop){
//service loop
}
}

If the server is a daemon process, it's a common practice to use SIGHUP to restart or re-initialize the server. #Joachim's answer is the most important, however: client behaviour shouldn't cause the server to terminate.
Note: Being asynchronous, there are restrictions on what signal handlers can do, safely.

Related

C signal (sigpipe, sighup) via Socket

I've to handle the SIGHUP and the SIGPIPE signal in order to avoid that a CLIENT, connected via Socket TCP, closing the terminal (The [X] of the GUI) hadn't to close or crash the SERVER.
I've set on the client a sigup handler like this
void sighup()
{
signal(SIGHUP, SIG_IGN);
system("echo SIGHUP received>>log.txt");
close(socket);
exit(0);
}
On the server I've set a SIGPIPE handler like this
signal(SIGPIPE,SIG_IGN);
but, if the client close the windows of the terminal, the server loops.
Any idea?
Thank you anyway for support
I did a mistake and I will put all check all write and read
istructions with perror. But, anyway, is that the right way to handle
the situation?
Ignoring SIGPIPE is viable. Alternatively you could prevent the generation of SIGPIPE by giving the MSG_NOSIGNAL flag to send().

Getting SIGPIPE with non-blocking sockets -- is this normal?

I'm writing an epoll-based network server in C. When I create my socket to listen for incoming connections, I make it non-blocking using fcntl. Similarly when incoming connections arrive from clients, I make their sockets non-blocking before doing anything with them, and likewise for outgoing connections' sockets.
Sometimes my server gets a SIGPIPE -- I think this is when I try to write to a client connection that has been closed by the client. This seems strange to me; I thought that with non-blocking sockets instead of a SIGPIPE I should get an -1 back from the call to write and ECONNRESET in errno.
Is there something I'm missing? Or is it just normal to get both a SIGPIPE and an error code even with non-blocking sockets (meaning that I should explicitly ignore the signal with signal(SIGPIPE, SIG_IGN) in my setup)?
Yes, this is normal. If you write to a socket (non-blocking or not) where the other end has closed the connection, you will get a SIGPIPE or (if you are blocking the SIGPIPE signal) an error return (-1) with errno set to EPIPE.
From the man page for write:
EPIPE: fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also receive
a SIGPIPE signal. (Thus, the write return value is seen only if the program catches, blocks or ignores this signal.)
The POSIX standard is here: http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html and says:
[EPIPE] An attempt is made to write to a pipe or FIFO that is not open for reading by any process, or that only has one end open. A SIGPIPE signal shall also be sent to the thread.
The SIGPIPE is normal. Another option beside setting signal handler solely for this purpose is to use flag MSG_NOSIGNAL whenever you send.

Closing a server socket in C linux

I have a server program which looks like this
{
socket();
bind();
listen();
while(1)
{
accept();
recv();
send();
close();
}
close();
}
Let's say the server is running, listening at the specified port. How can I close it by pressing a keypad? I mean a proper closure, not by Ctrl+C.
When you close() a socket that is blocking in accept(), then the accept() call will return immediately with -1.
If your program is single threaded like you show, then you can't do the above. You would need to introduce at least one additional thread to actually do the close().
Have the program install a signal handler (for SIGUSR1 for example) doing nothing.
Use setsockopt() to unset the option SA_RESTART for the sockets in use.
Make the code issuing socket related system calls aware that they might return with -1 and errno set to EINTR.
Run the program.
Send it a signal for which the program has a handler installed (in 1.) from the outside (by for example using the kill <pid> -USR1 command).
Detect the reception of a signal (see 3.) and react, for example by close()ing the socket in question.

How to cleanly interrupt a thread blocking on a recv call?

I have a multithreaded server written in C, with each client thread looking something like this:
ssize_t n;
struct request request;
// Main loop: receive requests from the client and send responses.
while(running && (n = recv(sockfd, &request, sizeof(request), 0)) == sizeof(request)) {
// Process request and send response.
}
if(n == -1)
perror("Error receiving request from client");
else if(n != sizeof(act))
fprintf(stderr, "Error receiving request from client: Incomplete data\n");
// Clean-up code.
At some point, a client meets a certain criteria where it must be disconnected. If the client is regularly sending requests, this is fine because it can be informed of the disconnection in the responses; However sometimes the clients take a long time to send a request, so the client threads end up blocking in the recv call, and the client does not get disconnected until the next request/response.
Is there a clean way to disconnect the client from another thread while the client thread is blocking in the recv call? I tried close(sockfd) but that causes the error Error receiving request from client: Bad file descriptor to occur, which really isn't accurate.
Alternatively, is there a better way for me to be handling errors here?
So you have at least these possibilities:
(1) pthread_kill will blow the thread out of recv with errno == EINTR and you can clean up and exit the thread on your own. Some people think this is nasty. Depends, really.
(2) Make your client socket(s) non-blocking and use select to wait on input for a specific period of time before checking if a switch used between the threads has been set to indicated they should shut down.
(3) In combo with (2) have each thread share a pipe with the master thread. Add it to the select. If it becomes readable and contains a shutdonw request, the thread shuts itself down.
(4) Look into the pthread_cancel mechanism if none of the above (or variations thereof) do not meet your needs.
Shutdown the socket for input from another thread. That will cause the reading thread to receive an EOS, which should cause it to close the socket and terminate if it is correctly written.
To interrupt the thread, make the socket non-blocking (set O_NONBLOCK using fcntl) and then signal the thread with pthread_kill. This way, recv will fail with either EINTR if it was sleeping, or EAGAIN or EWOULDBLOCK if it wasn’t (also maybe if SA_RESTART is in effect, didn’t check). Note that the socket doesn’t need to, and actually should not, be non-blocking before that. (And of course the signal needs to be handled; empty handler is sufficient).
To be sure to catch the stop-signal but not anything else, use a flag; there are things that may go wrong. For example, recv may fail with EINTR on some spurious signal. Or it may succeed if there was some data available, effectively ignoring the stop request.
And what not to do:
Don’t use pthread_kill alone or with any plain check. It may arrive right before issuing the recv syscall, too early to interrupt it but after all the checks.
Don’t close the socket. That may not even work, and as #R.. pointer out, is dangerous as the socket file descriptor may be reused between close and recv (unless you’re sure nothing opens file descriptors).

How to stop a read operation on a socket?

From one thread I got the following code:
int next_stuff(char **code){
...
len=read(file_desc,buffer+end_len,packet_size-end_len);
if(len<=0)
{
if(len==-1 && errno==EAGAIN) return(0);
else return(-1);
}
...
}
while (next_stuff(&buff) == 0)
{
...
}
On the other thread I'd like to finish that socket and exit this operation, but only doing a
close(file_desc);
does not cause read to return nonblocked. Am I missing something?
EDIT:
shutdown does not work as well. And I am trying that on Linux 2.6.23
shutdown(fd, SHUT_RD);
$ man -s 2 shutdown
NAME
shutdown -- shut down part of a full-duplex connection
SYNOPSIS
#include <sys/socket.h>
int shutdown(int socket, int how);
DESCRIPTION
The shutdown() call causes all or part of a full-duplex connection on the socket
associated with socket to be shut down.
If how is SHUT_RD, further receives will be disallowed. If how is
SHUT_WR, further sends will be
disallowed. If how is SHUT_RDWR, further sends and receives will be disallowed.
RETURN VALUES
The shutdown() function returns the value 0 if successful; otherwise the value -1 is
returned and the global variable errno is set to indicate the error.
In general, if you do not want blocking socket calls, you would use select() to see if the socket is ready to read, write, or is in the error state. In addition, pass a timeout value to select() so that this call isn't blocking forever. After the select() call returns, you can see if the application wants to quit and if so do the "right" thing (that's for you to decide).
If your read() call is nonblocking, it should return fairly fast, as all it will be doing is inserting memory.
To prevent doing any damage, you would use a mutex around your call to read() and close() such that they cant both run at the same time.
If your socket is blocking, i think you should make it nonblocking.
The other answers about non-blocking sockets are good, and I recommend recoding to use that approach.
As a direct answer to your question, though, try calling shutdown() and see if that will break the other thread out of read. I'm afraid close() is just decrementing the usage count, while shutdown() will actively tear down the socket.
I don't think you've provided enough information to answer this question, yet. For example if the socket that you've opened is UDP, then a close on the sending side will have no effect on the receiving side. If it is TCP, then something else is broken. I suggest that if you are really dealing with sockets, you use recv or recvfrom instead of read.
In the case of TCP, your read will return 0 bytes, an indication that the other side has closed the connection.
If you are really doing this between two threads instead of two processes, a pipe may be more appropriate. That's not to say that a pipe could not also be used between two separate processes, it just takes a bit more set up in that case.

Resources