closing a server socket

Alex Martelli aleax at aleax.it
Sat Oct 18 07:24:08 EDT 2003


Peter Hansen wrote:
   ...
> I guess you are basically saying that you want to use a blocking
> socket (because you can't get non-blocking ones to work, though they
> do work in general?) but you still want to be able to terminate
> your call from another thread by forcibly closing the socket...
> 
> If that's so, give it up.  You can't do that because the

VERY good point -- and since by a weird coincidence I've had to deal
with EXACTLY this problem TWICE over the last few days for two
different clients (!), both times in the context of xml-rpc serving,
let me emphasize this once again: that's not the way to do it.


> Use non-blocking sockets.  They do work.

Or architect a solution where the blocked thread will get out
from its stuck state in the blocking socket "naturally".  That's
quite easy in XML-RPC, e.g. as follows...:


_baseclass = SimpleXMLRPCServer.SimpleXMLRPCServer
class TerminatableServer(_baseclass):
    allow_reuse_address = True

    def __init__(self, addr, *args, **kwds):
        self.myhost, self.myport = addr
        _baseclass.__init__(self, addr, *args, **kwds)
        self.register_function(self.terminate_server)

    quit = False
    def serve_forever(self):
        while not self.quit:
            self.handle_request()
        self.server_close()

    def terminate_server(self, authentication_token):
        if not check_as_valid(authentication_token):
            return 1, "Invalid or expired authentication token"
        self.quit = True
        return 0, "Server terminated on host %r, port %r" % (
            self.myhost, self.myport)

(you'll want some way to verify authentication, of course, but
that's probably something you already have somewhere in such an
architecture, so I'm simplistically representing it by the
authentication_token parameter and a hypothetical check_as_valid
function that's able to check it).

The point is that in this way server termination is architected
as just one transaction -- the self.handle_request() in the body
of the while will eventually hand off control to terminate_server,
which may set self.quit, and that in turn will terminate the
while loop, since as soon as handle_request is done the loop's
condition is checked again.  There are other ways, of course, but
I've found this one clean and reliable for these specific needs.


Alex





More information about the Python-list mailing list