Interrupt read() on signal - c

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.

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".

How to stop poll() from being interrupted by a specific signal

I have a C application using poll to wait for some data.
Currently I am implementing the rest of my application into this one and I use time based interrupts (SIGRTMIN). As expected poll() returns if one of my other timers call back.
How can I stop poll from doing that? I am reading a lot about ppoll(), but not sure how to use that... Can I use this to stop this function from returning when a timer event is fired?
(I do not have any problems with the poll being delayed a few ms)
If a thread / process blocking in poll() receives an unblocked signal then poll() will be interrupted. If you don't want that to happen then you can block the desired signal before calling poll(), and then unblock it after poll() returns (see sigprocmask()). Note, however, that that won't cause poll() to be delayed -- quite the opposite. If anything, it will cause receipt of the signal to be delayed. If poll() blocks long enough then it could cause multiple RT signals to queue up, so that after you unblock that signal you receive it multiple times in quick succession.
You should consider instead checking poll()'s return value (which you should always do anyway) and retrying if it is EINTR.

A signal interrupts the send method in blocking mode

I'm programming with socket which is in blocking mode, I have a question about send method.
In the man page of send method, it says:
[EINTR] A signal interrupts the system call before any data is transmitted.
It means if a signal interrupts the system call before any data is transmitted, the send would return -1 and errno would be set to EINTR.
My question is that if a part of data has been transmitted when a signal interrupts the system call, what will return. It seems that it shouldn't return -1 because it has send some data. I think it will return the number of data has been transmitted which means send method in the blocking mode may return less number of data than you passed as third parameter.
ssize_t send(int socket, const void *buffer, size_t length, int flags);
The other answers are pretty clear, but after reading some of your comments, I would like to add some further information.
First of all, you got the idea behind EINTR wrong. Getting interrupted by a signal in a syscall is not to be perceived as an error. The rationale behind EINTR in slow syscalls (slow syscalls are those that can block forever, like open(2) on some file types - terminal devices for example - accept(2), read(2) and write(2) on some devices - sockets included - etc.) is that if your program was blocked in a syscall and a signal was caught (while still blocked), then it is very likely (but not mandatory) that the signal handler changed state in your program and things are different, so the call returns prematurely with EINTR to give you a chance of doing anything that you might want to do. It is not an error like EINVAL or EBADF or other "real" errors - it's just the way the kernel tells you that a signal was caught.
If you don't want to do anything, then either set the SA_RESTART flag on the sa_flags field of struct sigaction when setting up the signal handler (which causes the syscall to be automatically restarted), or explicitly call send(2) again when it returns -1 with errno set to EINTR.
The bottom line is, there isn't an inherent limitation on the kernel that forces it to return to userspace when signals are caught. Instead, EINTR is just a convenient behavior that developers might find useful.
If the kernel was in the midst of transmitting data and a signal was raised, it's no big deal: if data is being transmitted, the syscall is doing progress. The kernel is in process context executing a syscall in behalf of the program that called it, so technically the process is not sleeping anymore. If a signal arrives, it will be pending until the kernel decides that it's time to deliver it to the process - most likely, this happens once send(2) returns.
The documentation is clear.
RETURN VALUE
On success, these calls return the number of bytes sent. On error, -1 is returned, and errno is set appropriately.
[...]
EINTR A signal occurred before any data was transmitted;
send() either returns
the number of bytes sent
or -1
If -1 is returned the reason is indicated via the value of errno.
If errno equals EINTR a signal interupted send() while no data had been received so far.
From this info above one can safely conclude that if data had been received the send() function would not return -1, not matter whether a signal was received or not.
[EINTR] A signal interrupts the system call before any data is transmitted.
This means that if send() start transmitting data, it won't be interrupted by any signals. So, transmission will block the receiving of signal until it finishes. The situation that send() may return less bytes of data than you passed as third parameter is usually due to the network problems, such as packets lost.

Trying to exit from a blocking UDP socket read

This is a question similar to Proper way to close a blocking UDP socket. I have a thread in C which is reading from a UDP socket. The read is blocking. I would like to know if it is possible to be able to exit the thread, without relying on the recv() returning? For example can I close the socket from another thread and safely expect the socket read thread to exit? Didn't see any high voted answer on that thread, thats why I am asking it again.
This really depends on what system you're running under. For example, if you're running under a POSIX-compliant system and your thread is cancelable, the recv() call will be interrupted when you cancel the thread since it's a cancel point.
If you're using an older socket implementation, you could set a signal handler for your thread for something like SIGUSR1 and hope nobody else wanted it and signal, since recv() will interrupt on a signal. Your best option is not to block, if at all possible.
I don't think closing a socket involved in a blocking operation is a safe guaranteed way of terminating the operation. For instance, kernel.org warns darkly:
It is probably unwise to close file descriptors while they may be in
use by system calls in other threads in the same process. Since a
file descriptor may be reused, there are some obscure race conditions
that may cause unintended side effects.
Instead you could use a signal and make recv fail with EINTR
(make sure SA_RESTART is not enabled). You can send a signal to a
specific thread with pthread_kill
You could enable SO_RCVTIMEO on the socket before starting the recv
call
Personally I usually try to stay clear of all the signal nastiness but it's a viable option.
You've got a couple of options for that. A signal will interrupt the read operation, so all you need to do is make sure a signal goes off. The recv operation should fail with error number EINTR.
The simplest option is to set up a timer to interrupt your own process after some timeout e.g. 30 seconds:
itimerval timer
timeval time;
time.tv_sec = 30;
time.tv_usec = 0;
timer.it_value = time;
if( setitimer( ITIMER_REAL, &timer, NULL ) != 0 )
printf( "failed to start timer\n" );
You'll get a SIGALRM after the specified time, which will interrupt your blocking operation, and give you the chance to repeat the operation or quit.
You cannot deallocate a shared resource while another thread is or might be using it. In practice, you will find that you cannot even write code to do what you suggest.
Think about it. When you go to call close, how can you possibly know that the other thread is actually blocked in recv? What if it's about to call recv, but then another thread calls socket and gets the descriptor you just closed? Now, not only will that thread not detect any error, but it will be calling recv on the wrong socket!
There is probably a good way to solve your outer problem, the reason you need to exit from a blocking UDP socket read. There are also several ugly hacks available. The basic approach is to make the socket non-blocking and instead of making a blocking UDP socket read, fake a blocking read with select or poll. You can then abort this loop several ways:
One way is to have select time out and check an 'abort' flag when select returns.
Another way is to also select on the read end of a pipe. Send a single byte to the pipe to abort the select.
If posix complient system, you can try to monitor your thread:
pthread_create with a function that makes your recv and pthread_cond_signal just after, then returns.
The calling thread makes a pthread_cond_timedwait with the desired timeout and terminates the called thread if timed_out.

Can a socket be closed from another thread when a send / recv on the same socket is going on?

Can a socket be closed from another thread when a send / recv on the same socket is going on?
Suppose one thread is in blocking recv call and another thread closes the same socket, will the thread in the recv call know this and come out safely?
I would like to know if the behavior will differ between different OS / Platforms. If yes, how will it behave in Solaris?
In linux closing a socket won't wake up recv(). Also, as #jxh says:
If a thread is blocked on recv() or send() when the socket is closed
by a different thread, the blocked thread will receive an error.
However, it is difficult to detect the correct remedial action after
receiving the error. This is because the file descriptor number
associated with the socket may have been picked up by yet a different
thread, and the blocked thread has now been woken up on an error for a
"valid" socket. In such a case, the woken up thread should not call
close() itself.
The woken up thread will need some way to differentiate whether the
error was generated by the connection (e.g. a network error) that
requires it to call close(), or if the error was generated by a
different thread having called close() on it, in which case it should
just error out without doing anything further to the socket.
So the best way to avoid both problems is to call shutdown() instead of close(). shutdown() will make the file descriptor still available, so won't be allocated by another descriptor, also will wake up recv() with an error and the thread with the recv() call can close the socket the normal way, like a normal error happened.
I don't know Solaris network stack implementation but I'll throw out my theory/explanation of why it should be safe.
Thread A enters some blocking system call, say read(2), for this given socket. There's no data in socket receive buffer, so thread A is taken off the processor an put onto wait queue for this socket. No network stack events are initiated here, connection state (assuming TCP) has not changed.
Thread B issues close(2) on the socket. While kernel socket structure should be locked while thread B is accessing it, no other thread is holding that lock (thread A released the lock when it was put to sleep-wait). Assuming there's no outstanding data in the socket send buffer, a FIN packet is sent and the connection enters the FIN WAIT 1 state (again I assume TCP here, see connection state diagram)
I'm guessing that socket connection state change would generate a wakeup for all threads blocked on given socket. That is thread A would enter a runnable state and discover that connection is closing. The wait might be re-entered if the other side has not sent its own FIN, or the system call would return with eof otherwise.
In any case, internal kernel structures will be protected from inappropriate concurrent access. This does not mean it's a good idea to do socket I/O from multiple threads. I would advise to look into non-blocking sockets, state machines, and frameworks like libevent.
For me, shutdown() socket from another thread do the job in Linux
If a thread is blocked on recv() or send() when the socket is closed by a different thread, the blocked thread will receive an error. However, it is difficult to detect the correct remedial action after receiving the error. This is because the file descriptor number associated with the socket may have been picked up by yet a different thread, and the blocked thread has now been woken up on an error for a "valid" socket. In such a case, the woken up thread should not call close() itself.
The woken up thread will need some way to differentiate whether the error was generated by the connection (e.g. a network error) that requires it to call close(), or if the error was generated by a different thread having called close() on it, in which case it should just error out without doing anything further to the socket.
Yes, it is ok to close the socket from another thread. Any blocked/busy threads that are using that socket will report a suitable error.

Resources