Closing a server socket in C linux - c

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.

Related

How to terminate a socket accept blocking

I developed a server with C code.
I used the accept() function to keep my server listening on a giving socket.
My server is launched in a thread.
Now in other thread and for some condition I want to stop the accept() blocking and then close the related socket.
How I can do that? Could shutdown() do that?
[This does not work on Windows]
Use sigaction() to install a signal handler for let's say SIGUSR1 doing nothing, but having the SA_RESTART option unset (also see section "Interruption of system calls and library functions by signal handlers" on this man-page).
Then send the blocking process a SIGUSR1 signal.
accept() will then return -1 and set errno to EINTR.
Classically, closing the socket from another thread causes the accept() call to return with an error. I have been told that this does not work on some releases of Linux, but have seen no evidence of that myself - every time, on Windows/Linux, the accept() returns with an error/exception.
The other common solution is to check some 'shutdown' atomic boolean after every accept() return. When you want to stop it, set the boolean and perform a connect() on the localhost stack, so causing the accept() to return in the 'normal' way.
I was having trouble with accept not terminating after I only called close on the socket under Linux Mint 18.3. I solved it by also calling shutdown(socket_fd, SHUT_RD); before the close
mah already mentioned it, but I wanted to highlight this, because this is the first SO result in a google search for "socket stop accept".

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().

Interrupt read() on signal

I have a thread that continuously reads a serial port for data.
If the main program receives a SIGINT it calls g_thread_join() on the serial port thread.
However, since the read is blocking the serial port thread won't return and program stalls untill i get a byte on the serial line and then it can exit.
Is there a way to pass the SIGINT on to read() so that it can be forced to return when the main thread demands it?
To have read() return EINTR, unset SA_RESTART in the member sa_flags of the struct sigaction passed into the call to sigaction() when installing the signal handler for SIGINT.
An alternative approach woud be to avoid a blocking read() at all. Please see the answers to this question: how to avoid blocking from the read function?
The accepted answer for this previous question on implementing timeout for read() when reading from a serial port shows how to use select(2) to perform reading with timeout. The SIGINT signal you send will thus be eventually acted upon.

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.

Handling Ctrl-C in a Linux TCP/IP Server written in C

I'm currently working on a Linux TCP/IP server. The server program is running in C. I'm currently testing it, but each time I exit it with Ctrl-c, the port it's using is not released, neither is the database it's been writing to unlocked. How does one define a subroutine that will exit when a Ctrl+C signal is received?
Lookup setsockopt and SO_REUSEADDR. This option must have been set on the old original server process's socket or the new one will not be able to bind the port until the TIME_WAIT period expires.
#Bortds Generally the port won't be released immediately, you have to wait to for some time. I found this from a server project I worked.
Two options:
Add a cleanup routine with: int atexit(void (*function)(void));
Hook Ctrl+C with: sighandler_t signal(int signum, sighandler_t handler);
As R pointed out, sigaction is more portable than signal, but perhaps less idiomatic for Linux.
Warning: atexit routines won't run if your program is killed with SIGKILL (Ctrl+/) or any other unhandled signal is received.

Resources