Possible Duplicate:
Wake up thread blocked on accept() call
I am writing a small server which listening for connections (accepting them and passing them to worker threads) until a custom stop signal is sent.
If I use blocking sockets, then my main accept loop cannot break on the custom stop signal being sent. However, I wish to avoid having a busy-wait/spinlock loop with a non-blocking socket.
What I want is for my main accept loop to block until either a connection is received or the stop signal is sent.
Is this possible in C on Linux?
Many Thanks.
If I understand correctly then you are open to using any kind of "signal", not necessarily a POSIX signal. Actually, POSIX signals are a poor choice because checking if you have received one in a loop has unavoidable race conditions.
What you need to use is anything that can be monitored through a file descriptor. It could be:
The later entries in the list of examples aren't generally practical. They're just to illustrate that it can be any type of object as long as it is has monitorable file descriptor. The simplest, cheapest, and most popular way is a pipe.
If you are already using nonblocking sockets, then you certainly already have some kind of polling loop to check when they're ready to accept connections. I'm going to assume you're using
poll()
to do this.Before you start your loop, set up a pipe like this:
The
fcntl
is to set the read end of the pipe to non blocking mode. You're going to be using that end of the pipe in yourpoll
call together with your socket, so it needs to be nonblocking.Then just add the read end of the pipe to the list of tile descriptors that you monitor in your accept loop:
The example uses
poll
but you might be usingselect
(or evenepoll
) instead.select
has a different interface but the idea is the same.This technique is known as the self-pipe trick.
If you do not to want pass an unblocking socket to accpet(), then sending a signal (as described by
man signal
to theaccept()
ing thread is the only way to interrupt a blockingaccept()
(waiting for connections).As already pointed out by some commenters most system calls (including
accept()
) will be interupted when their thread received a signal.If
accept()
returns-1
anderrno
is set toEINTR
the call toaccept()
was interupted by a signal.To send a signal to a process use
kill(<pid>, <signal-number>)
.If you are in a multi-threaded enviroment, block the signal you'll be using (typical
SIGUSR1
orSIGUSR2
) for all other threads, but the thread that callsaccept()
, asi t is nondeterministic which thread of a process will handle a signal sent to a process ("addressed" via the process'pid
.)Alternativly you can use
pthread_kill(<pthread>, <signal-number>)
to send a signal to a specific thread only.