How to stop BaseHTTPServer.serve_forever () in a subclass of BaseHTTPRequestHandler?

I start my HTTPServer in a separate thread (using a streaming module that does not have the ability to stop streams ...) and wants to stop submitting requests when the main thread also shuts down.

The Python documentation states that BaseHTTPServer.HTTPServer is a subclass of SocketServer.TCPServer that supports the shutdown method, but it is not in HTTPServer .

The entire BaseHTTPServer module has very little documentation BaseHTTPServer

+28
Nov 06 '08 at 13:10
source share
7 answers

I must start by saying that "I probably would not have done it myself, but I had in the past." The serve_forever method (from SocketServer.py) looks like this:

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

You can replace (in a subclass) while 1 with while self.should_be_running and change this value from another 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 that I used at that 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() 
+19
Nov 06 '08 at 13:21
source

In my python 2.6 installation, I can call it on the base TCPServer - it is still 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>> >>> 
+17
Nov 06 '08 at 13:30
source

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

+13
Oct 26 2018-10-10T00:
source

Another way to do this based on http://docs.python.org/2/library/basehttpserver.html#more-examples is: instead of serve_forever (), continue to work until the condition is satisfied, checking the status of the server with and before after each request. For example:

 import CGIHTTPServer import BaseHTTPServer KEEP_RUNNING = True def keep_running(): return KEEP_RUNNING class Handler(CGIHTTPServer.CGIHTTPRequestHandler): cgi_directories = ["/cgi-bin"] httpd = BaseHTTPServer.HTTPServer(("", 8000), Handler) while keep_running(): httpd.handle_request() 
+9
Oct 06 '13 at 17:32
source

In python 2.7, the shutdown () call works, but only if you serve through serve_forever, because it uses async select and a polling loop. Carrying out our own loop using handle_request (), ironically, eliminates this functionality because it involves a dumb blocking call.

With SocketServer.py BaseServer:

 def serve_forever(self, poll_interval=0.5): """Handle one request at a time until shutdown. Polls for shutdown every poll_interval seconds. Ignores self.timeout. If you need to do periodic tasks, do them in another thread. """ self.__is_shut_down.clear() try: while not self.__shutdown_request: # XXX: Consider using another file descriptor or # connecting to the socket to wake this up instead of # polling. Polling reduces our responsiveness to a # shutdown request and wastes cpu at all other times. r, w, e = select.select([self], [], [], poll_interval) if self in r: self._handle_request_noblock() finally: self.__shutdown_request = False self.__is_shut_down.set() 

Here is part of my code to block shutdown from another thread, using an event to wait for completion:

 class MockWebServerFixture(object): def start_webserver(self): """ start the web server on a new thread """ self._webserver_died = threading.Event() self._webserver_thread = threading.Thread( target=self._run_webserver_thread) self._webserver_thread.start() def _run_webserver_thread(self): self.webserver.serve_forever() self._webserver_died.set() def _kill_webserver(self): if not self._webserver_thread: return self.webserver.shutdown() # wait for thread to die for a bit, then give up raising an exception. if not self._webserver_died.wait(5): raise ValueError("couldn't kill webserver") 
+9
Mar 18 '14 at 23:38
source

Event contours end with SIGTERM, Ctrl + C, or when shutdown() called.

server_close() must be called after server_forever() to close the listening socket.

 import http.server class StoppableHTTPServer(http.server.HTTPServer): def run(self): try: self.serve_forever() except KeyboardInterrupt: pass finally: # Clean-up server (close socket, etc.) self.server_close() 

A simple server stops with user action (SIGTERM, Ctrl + C , ...):

 server = StoppableHTTPServer(("127.0.0.1", 8080), http.server.BaseHTTPRequestHandler) server.run() 

The server runs in the stream:

 import threading server = StoppableHTTPServer(("127.0.0.1", 8080), http.server.BaseHTTPRequestHandler) # Start processing requests thread = threading.Thread(None, server.run) thread.start() # ... do things ... # Shutdown server server.shutdown() thread.join() 
+5
Feb 23 '16 at 11:18
source

I tried all of the above solution and ended up having a β€œonce” problem - somehow it didn't actually do it, so I ended up doing a dirty solution that worked all the time for me:

If all of the above fails, then brute force kills your thread using something like this:

 import subprocess cmdkill = "kill $(ps aux|grep '<name of your thread> true'|grep -v 'grep'|awk '{print $2}') 2> /dev/null" subprocess.Popen(cmdkill, stdout=subprocess.PIPE, shell=True) 
0
Feb 12 '16 at 8:41
source



All Articles