In general, ctrl-c should work to stop a tornado server. (One known
exception is if you're using debug mode/autoreload on Windows or older
versions of Mac OS). However, there are a number of
non-tornado-specific ways that ctrl-c handling can go awry in python.
The most likely culprit is either a background thread without the
daemon attribute set, or if you're blocking on a call to a C function
that is not interruptible (Many of the synchronization methods in the
threading module are not interruptible when called without timeouts.
I'm sure there are non-threading-related examples too, but these are
the ones I run into the most). You can make ctrl-c more forceful (at
the expense of not printing a stack trace or running any finally
blocks when it happens) by running signal.signal(signal.SIGINT,
signal.SIG_DFL) at the start of your program.
My recommendation for combining multiple event loops is to give each
one its own thread. Use IOLoop.add_callback to transfer control from
the QT thread to the tornado thread, and an analogous method to send
things from tornado to QT. Be sure to use locks for any shared data
structures.
-Ben