You have to periodically check for pending signals, for example, on every Nth iteration of the simulation loop:
from cpython.exc cimport PyErr_CheckSignals
cdef Run(self):
while True:
# do some work
PyErr_CheckSignals()
PyErr_CheckSignals
will run signal handlers installed with signal module (this includes raising KeyboardInterrupt
if necessary).
PyErr_CheckSignals
is pretty fast, it's OK to call it often. Note that it should be called from the main thread, because Python runs signal handlers in the main thread. Calling it from worker threads has no effect.
Explanation
Since signals are delivered asynchronously at unpredictable times, it is problematic to run any meaningful code directly from the signal handler. Therefore, Python queues incoming signals. The queue is processed later as part of the interpreter loop.
If your code is fully compiled, interpreter loop is never executed and Python has no chance to check and run queued signal handlers.