Stopping Python socketserver.ThreadingTCPServer On Keyboard Interrupt

2021-12-02
Python
ThreadingTCPServer
server
programming

socketserver.ThreadingTCPServer

Curiously enough, Python documentation suggests writing async TCP server using mixins (see https://docs.python.org/3/library/socketserver.html#socketserver.ThreadingMixIn) while there's existing class that does it already hence not requiring boilerplate code - ant it's socketserver.ThreadingTCPServer.

Its usage is pretty much like socketserver.TCPServer in the documentation - here's an echo-like server example:

class TCPServerHandler(socketserver.StreamRequestHandler):
    def handle(self):
        data_line: str = "_"
        data_processor = DataProcess()
        while data_line:
            data_line = self.rfile.readline().strip().decode('ascii')
            if data_line == '.':
                print("Connection terminated by client request")
                self.finish()
                return
            self.request.sendall(data_line)

with socketserver.ThreadingTCPServer(("localhost", 5000), TCPServerHandler) as server:
    try:
        server.daemon_threads = True
        server.serve_forever()
    except (KeyboardInterrupt, SystemExit):
        log.error("Shutdown signal received")
    finally:
        print('Stopping server')
        server.server_close()

Stopping the server

And it's all nice and fine, with one exception - the using code from the documentation doesn't stop on the keyboard interrupt. Which is annoying as the search for the problem brings many (valid) discussions on how the keyboard events are relevant to the main thread only so the server isn't responsible for it, but there was no valid solution - setting the recommended server.daemon = True flag did nothing.

The solution was surprisingly simple and intuitive, but not really described anywhere - to use the server.daemon_threads = True flag instead! Oh well...

I'll leave it here in case it pops up in someone's search and helps with the problem.