views:

3021

answers:

3

The python documentation states that BaseHTTPServer.HTTPServer is a subclass of SocketServer.TCPServer, which dows support a shutdown method - but it is missing in HTTPServer.

I am running my HTTPServer in a separate thread (using the threading module which has no way to stop threads...) and want to stop serving requests when the main thread also shuts down.

The whole BaseHTTPServer module has very little documentation :(

+5  A: 

I should start by saying that "I probably wouldn't do this myself, but I have in the past". The serve_forever (from SocketServer.py) method looks like this:

def serve_forever(self):
    """Handle one request at a time until doomsday."""
    while 1:
        self.handle_request()

You could replace (in subclass) while 1 with while self.should_be_running, and modify that value from a different thread. Something like:

def stop_serving_forever(self):
    """Stop handling requests"""
    self.should_be_running = 0
    # Make a fake request to the server, to really force it to stop.
    # Otherwise it will just stop on the next request.
    # (Exercise for the reader.)
    self.make_a_fake_request_to_myself()

Edit: I dug up the actual code I used at the time:

class StoppableRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):

    stopped = False
    allow_reuse_address = True

    def __init__(self, *args, **kw):
        SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, *args, **kw)
        self.register_function(lambda: 'OK', 'ping')

    def serve_forever(self):
        while not self.stopped:
            self.handle_request()

    def force_stop(self):
        self.server_close()
        self.stopped = True
        self.create_dummy_request()

    def create_dummy_request(self):
        server = xmlrpclib.Server('http://%s:%s' % self.server_address)
        server.ping()
Ali A
I think you can call "self.serve_forever()" after "self.stopped = True" and avoid implementing "create_dummy_request(self)". It's worked for me so far, but there may be a subtlety that I'm missing.
Jeff Hammerbacher
+2  A: 

In my python 2.6 installation, I can call it on the underlying TCPServer - it still there inside your HTTPServer:

TCPServer.shutdown


>>> import BaseHTTPServer
>>> h=BaseHTTPServer.HTTPServer(('',5555), BaseHTTPServer.BaseHTTPRequestHandler)
>>> h.shutdown
<bound method HTTPServer.shutdown of <BaseHTTPServer.HTTPServer instance at 0x0100D800>>
>>>
gimel
ah. yes, and I *am* reading the 2.6 docs - alas, I'm running 2.5. Bummer. Me idiot.
Daren Thomas
A: 

I think you can use [serverName].socket.close()

wimerrill