I am working on a "simple" server using a threaded SocketServer in Python 3.
I am going through a lot of trouble implementing shutdown for this. The code below I found on the internet and shutdown works initially but stops working after sending a few commands from the client via telnet. Some investigation tells me it hangs in threading._shutdown... threading._wait_for_tstate_lock but so far this does not ring a bell.
My research tells me that there are ~42 different solutions, frameworks, etc. on how to do this in different python versions. So far I could not find a working approach for python3. E.g. I love telnetsrv(https://pypi.python.org/pypi/telnetsrv/0.4) for python 2.7 (it uses greenlets from gevent) but this one does not work for python 3. So if there is a more pythonic, std lib approach or something that works reliably I would love to hear about it!
My bet currently is with socketserver but I could not figure out yet how to deal with the hanging server. I removed all the log statements and most functionality so I can post this minimal server which exposes the issue:
# -*- coding: utf-8 -*-
import socketserver
import threadingSERVER = Nonedef shutdown_cmd(request):global SERVERrequest.send(bytes('server shutdown requested\n', 'utf-8'))request.close()SERVER.shutdown()print('after shutdown!!')#SERVER.server_close()class service(socketserver.BaseRequestHandler):def handle(self):while True:try:msg = str(self.request.recv(1024).strip(), 'utf-8')if msg == 'shutdown':shutdown_cmd(msg, self.request)else:self.request.send(bytes("You said '{}'\n".format(msg), "utf-8"))except Exception as e:passclass ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):passdef run():global SERVERSERVER = ThreadedTCPServer(('', 1520), service)server_thread = threading.Thread(target=SERVER.serve_forever)server_thread.daemon = Trueserver_thread.start()input("Press enter to shutdown")SERVER.shutdown()if __name__ == '__main__':run()
It would be great being able to stop the server from the handler, too (see shutdown_cmd)