"Chris Angelico" <ros...@gmail.com> wrote in message
news:mailman.8.1442612439.21674.python-l...@python.org...
On Sat, Sep 19, 2015 at 3:17 AM, James Harris
<james.harri...@gmail.com> wrote:
Needless to say, on a test Windows machine AF_UNIX is not present.
The only
cross-platform option, therefore, seems to be to use each subthread's
select()s to monitor two AF_INET sockets: the one to the client and a
control one from the master thread. I would seem to need IP socket
pairs
between the master thread and the subthreads. If the master thead
receives a
shutdown signal it will send a shutdown command to each subthread.
The above seems logical but would use quite a few IP sockets. I
cannot think
of a better way, though. Any comments on the ideas above?
If you're using select() to monitor the sockets, you don't actually
then have to _do_ anything with the shutdown socket. You could have a
single socket that sends the shutdown signal to all your workers.
I don't understand how a single socket could send the signal to all the
workers. I did consider some form of multicast but thought it too
complicated (and possibly infeasible).
Re. not understanding the single sending socket idea that you mention
perhaps I had better explain a bit of what I had in mind:
1. A worker thread would have a TCP socket connection to its client, and
another socket for communicating with the master. That second socket has
to be AF_INET for portability. It could be TCP or UDP. A connected UDP
socket may be most appropriate and seems worth trying.
2. If something happens to the master thread so that it determines that
the application should shut down it would iterate over the sockets to
the workers and tell each one to shut down. It would then shut itself
down. (Am not sure at the moment whether to wait for the worker
threads.)
3. A worker thread, being told to shutdown (basically a single byte
received from the master thread) would tell its client to close the TCP
connection and then it would wait a little while for it to do so - maybe
a second or two. When the client closes the TCP connection (or the
timeout wait period expires) the worker thread will close its end and
exit.
Bear in mind, though, that Windows has no protection against other
processes shutting you down. You can restrict it to 127.0.0.1 (of
course) but any program running on the same computer as the server -
regardless of user permissions etc - will be able to connect to your
sockets.
I was thinking of a connected UDP socket. That way, AIUI, at least in
the absence of forged datagrams, only the master thread will be able to
communicate with the worker, due to connected UDP sockets demulitplexing
datagrams based on their source as well as their destination, i.e. on a
5-tuple (UDP, source IP, source port, destination IP, destination port).
So it might be best to do something like this (all on the
main thread):
1) Open a listening socket
2) Connect to the listening socket
3) Accept a connection
4) Close the original listening socket
5) Spin off all your threads, passing them the socket from step 2
6) To terminate them all, write a byte to the socket from step 3.
That sounds similar to what I had in mind but I am not sure why you
would close the listening socket. Connections could come in at any time
and threads could therefore be needed at any time so I was thinking that
the master thread (the one with the listening TCP socket) would just sit
waiting for new connection requests (or an interrupting signal).
In reality, due to Windows not recognising signals while in the accept()
call I think there would be a real master thread and a listening thread
but I have omitted that in the descriptions above. As far as the normal
worker threads are concerned they would be ready to be told to shut down
by the listening thread, and it would be ready to be told to shut down
by the master thread. Still with me? ;-)
This will make it difficult for ordinary userspace code to mess with
you. It'd still be possible, I think, for something with raw sockets
access to feign a termination signal; I have no idea what protections
Windows offers you there.
Yes, something which could forge a packet could tell a worker to close
down. I don't think there's any significant problem here, thought,
because:
* other programs are similarly vulnerable to forged packets
* the only forgery effect is to tell a worker thread to stop - not a big
loss
* the shutdown protocol would/should cause the client to re-request
* a forger would have to know the specific port number used by the
master thread to communicate with that particular worker, and the port
number that worker was using.
Overall, I think it would be more than robust enough.
Notwithstanding your comment about a single socket, above, no one seems
so far to have objected to the number of sockets this would need, which
was my main concern, so that's good!
James
--
https://mail.python.org/mailman/listinfo/python-list