Reputation: 3654
I have the following "main" code:
with http.server.ThreadingHTTPServer( ("", port), Handler ) as daemon:
print(f"serving on port {port} process {os.getpid()} ")
while True:
try:
daemon.handle_request()
except KeyboardInterrupt:
print("\nexiting")
return 0
which works great. However - this is only used for local testing and on the ci machine - so I want an easy way to shut it down and replace it with the next one - so inside the Handler do_GET(self) I added the following code:
if path == "/shutdown":
throw Exception("shut down")
and if I do a curl http://localhost:9000/shutdown.... I do indeed see an exception - nicely displayed and swallowed inside the thread.
And I've found it remarkably hard to figure out any way of stopping the server from inside the handler - because the handler is running in another process.
Is there a simple way of doing it?
Upvotes: 1
Views: 243
Reputation: 1
You can spawn another thread and call the server's shutdown method, like so:
import http.server
import threading
from http import HTTPStatus
class Handler(http.server.SimpleHTTPRequestHandler):
def do_STOP(self):
# Make sure we send a valid response for the current request.
# Here, we simply send a "204 No content" error response.
self.send_error(HTTPStatus.NO_CONTENT)
# This will send the shutdown signal to the server.
# New requests will not be processed after that.
threading.Thread(target=self.server.shutdown).start()
with http.server.ThreadingHTTPServer(("", 0), Handler) as httpd:
print("Listening on port", httpd.server_address[1])
httpd.serve_forever()
As noted in the source code for socketserver.BaseServer
(of which ThreadingHTTPServer
is a derived class), shutdown()
must be called from a different thread to avoid a deadlock:
def shutdown(self):
"""Stops the serve_forever loop.
Blocks until the loop has finished. This must be called while
serve_forever() is running in another thread, or it will
deadlock.
"""
Upvotes: 0