Further topics in interrupt/signal handling¶
When writing documentation, one sometimes wants to check that certain
code can be interrupted in a clean way. The best way to do this is to
The following is an example of a doctest demonstrating that the
factor() can be interrupted:
>>> from cysignals.alarm import alarm, AlarmInterrupt >>> try: ... alarm(0.5) ... factor(10**1000 + 3) ... except AlarmInterrupt: ... print("alarm!") alarm!
If you use the SageMath doctesting framework, you can instead doctest
the exception in the usual way (the Python
doctest module exits
KeyboardInterrupt is raised in a doctest).
To avoid race conditions, make sure that the calls to
the function you want to test are in the same doctest:
>>> alarm(0.5); factor(10**1000 + 3) Traceback (most recent call last): ... AlarmInterrupt
Signal handling without exceptions¶
There are several more specialized functions for dealing with interrupts. As
sig_on() makes no attempt to clean anything up (restore
state or freeing memory) when an interrupt occurs. In fact, it would be
sig_on() to do that. If you want to add some cleanup code,
sig_on_no_except() for this. This function behaves exactly like
sig_on(), except that any exception raised (like
RuntimeError) is not yet passed to Python. Essentially, the exception is
there, but we prevent Cython from looking for the exception. Then
cython_check_exception() can be used to make Cython look for the exception.
sig_on_no_except() returns 1. If a signal was caught and an
sig_on_no_except() instead returns 0. The following
example shows how to use
def no_except_example(): if not sig_on_no_except(): # (clean up messed up internal state) # Make Cython realize that there is an exception. # It will look like the exception was actually raised # by cython_check_exception(). cython_check_exception() # (some long computation, messing up internal state of objects) sig_off()
There is also a function
sig_str_no_except(s) which is analogous to
See the file src/cysignals/tests.pyx
for more examples of how to use the various
Releasing the Global Interpreter Lock (GIL)¶
All the functions related to interrupt and signal handling do not require the
(if you don’t know what this means, you can safely ignore this section), they
nogil. This means that they can be used in Cython code inside
with nogil blocks. If
sig_on() needs to raise an exception, the GIL is
temporarily acquired internally.
If you use C libraries without the GIL and you want to raise an exception before calling sig_error(), remember to acquire the GIL while raising the exception. Within Cython, you can use a with gil context.
The GIL should never be released or acquired inside a
sig_on() block. If
you want to use a
with nogil block, put both
sig_off() inside that block. When in doubt, choose to use
sig_check() instead, which is always safe to use.