CherryPy interferes with Twisted shutting down on Windows
cherrypy, linux, python, twisted, windows
Solution
CherryPy handles signals by default when you call quickstart. In your case, you should probably just unroll quickstart, which is only a few lines, and pick and choose. Here's basically what quickstart does in trunk:
if config:
cherrypy.config.update(config)
tree.mount(root, script_name, config)
if hasattr(engine, "signal_handler"):
engine.signal_handler.subscribe()
if hasattr(engine, "console_control_handler"):
engine.console_control_handler.subscribe()
engine.start()
engine.block()
In your case, you don't need the signal handlers, so you can omit those. You also don't need to call engine.block if you're not starting CherryPy from the main thread. Engine.block() is just a way to make the main thread not terminate immediately, but instead wait around for process termination (this is so autoreload works reliably; some platforms have issues calling execv from any thread but the main thread).
If you remove the block() call, you don't even need the Thread() around quickstart. So, replace your line:
Thread(target=cherrypy.quickstart, args=[Root()]).start()
with:
cherrypy.tree.mount(Root())
cherrypy.engine.start()
Problem
I've got an application that runs Twisted by starting the reactor with `reactor.run()` in my main thread after starting some other threads, including the CherryPy web server. Here's a program that shuts down cleanly when Ctrl+C is pressed on Linux but not on Windows: ``` from threading import Thread from signal import signal, SIGINT import cherrypy from twisted.internet import reactor from twisted.web.client import getPage def stop(signum, frame): cherrypy.engine.exit() reactor.callFromThread(reactor.stop) signal(SIGINT, stop) class Root: @cherrypy.expose def index(self): reactor.callFromThread(kickoff) return "Hello World!" cherrypy.server.socket_host = "0.0.0.0" Thread(target=cherrypy.quickstart, args=[Root()]).start() def print_page(html): print(html) def kickoff(): getPage("http://acpstats/account/login").addCallback(print_page) reactor.run() ``` I believe that CherryPy is the culprit here, because here's a different program that I wrote without CherryPy that does shutdown cleanly on both Linux and Windows when Ctrl+C is pressed: ``` from time import sleep from threading import Thread from signal import signal, SIGINT from twisted.internet import reactor from twisted.web.client import getPage keep_going = True def stop(signum, frame): global keep_going keep_going = False reactor.callFromThread(reactor.stop) signal(SIGINT, stop) def print_page(html): print(html) def kickoff(): getPage("http://acpstats/account/login").addCallback(print_page) def periodic_downloader(): while keep_going: reactor.callFromThread(kickoff) sleep(5) Thread(target=periodic_downloader).start() reactor.run() ``` Does anyone have any idea what the problem is? Here's my conundrum: - On Linux everything works - On Windows, I can call functions from signal handlers using `reactor.callFromThread` when CherryPy is not running - When CherryPy is running, no function that I call using `reactor.callFromThread` from a signal handler will ever execute (I've verified that the signal handler itself does get called) What can I do about this? How can I shut down Twisted on Windows from a signal handler while running CherryPy? Is this a bug, or have I simply missed some important part of the documentation for either of these two projects?