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