cysignals
cysignals is a Python library designed for robust interrupt and signal handling within Cython code. It provides mechanisms to ensure that long-running Cython computations can be interrupted (e.g., via CTRL-C) and offers a Python interface for managing OS-level signal handlers and system calls like `pselect()` and `sigprocmask()`. The library is currently at version 1.12.6, actively maintained by the SageMath community, and receives regular updates to support newer Python and Cython versions.
Common errors
-
error: cysignals must be compiled without _FORTIFY_SOURCE
cause The `_FORTIFY_SOURCE` macro, often enabled by default in some compilation environments for security, conflicts with cysignals' low-level signal handling.fixDisable `_FORTIFY_SOURCE` during compilation. This typically involves adding `-U_FORTIFY_SOURCE` or `-D_FORTIFY_SOURCE=0` to CFLAGS in your build configuration. -
configure: error: source directory already configured; run "make distclean" there first
cause This error occurs when attempting to configure or build cysignals after a previous (possibly failed) build attempt without proper cleanup, especially in older build systems.fixNavigate to the source directory of cysignals and run `make distclean` before attempting to configure or build again. For newer Meson-based builds, you might need to remove the build directory. -
Unhandled SIGSEGV during signal handling. This probably occurred because a *compiled* module has a bug in it and is not properly wrapped with sig_on(), sig_off(). Python will now terminate.
cause A segmentation fault (SIGSEGV) occurred within a compiled module, likely a Cython extension, and was not properly handled by `cysignals`' `sig_on()`/`sig_off()` context. This indicates a low-level memory error or an unhandled signal in native code.fixInspect the Cython code for potential memory issues or improper handling of C library calls. Ensure all critical C/Cython blocks are properly wrapped with `sig_on()` and `sig_off()` calls, and that no Python interaction occurs within these blocks. Debug with GDB for a more detailed backtrace if cysignals' crash hook does not provide enough information. -
ERROR: Command errored out with exit status 1: command: /path/to/python -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = ... /setup.py' install ...
cause This generic error during `pip install` often indicates a compilation failure of the Cython extensions, potentially due to missing build dependencies (e.g., Cython, a C compiler), environment misconfiguration, or issues with older `setuptools`-based builds interacting with newer Python versions/packaging standards.fixEnsure `Cython` and a C compiler (like GCC or Clang) are installed and accessible in your environment. For newer Python versions and `cysignals`, verify `meson-python` is available. Review the full error output for specific compiler messages. Consider `pip install --no-build-isolation cysignals` as a diagnostic step or to work around build environment issues.
Warnings
- breaking cysignals versions 1.12.0 and later removed the optional compile-time dependency on PARI/GP. If your Cython code relied on the `_pari_version` function or the `sig_error()` mechanism for PARI, you will need to adjust your build process or error handling.
- breaking Version 1.12.6 dropped support for older Python versions, now requiring Python 3.12 or newer. Previous versions (e.g., 1.11.0) similarly dropped Python 2 support and bumped the minimum to 3.6.
- gotcha When using `sig_on()` and `sig_off()` in Cython, they must always be called in pairs, and `sig_off()` must be executed before the function calling `sig_on()` returns (including all return or raise paths). The code within `sig_on()` and `sig_off()` should be pure C or Cython, as calling Python code or manipulating Python objects can lead to corrupted internal state if an interrupt occurs. Use `sig_check()` if you are unsure.
- gotcha Compiling cysignals with `_FORTIFY_SOURCE` enabled can lead to compilation errors.
- deprecated The build system for cysignals transitioned to Meson in version 1.12.0. Older `setuptools`-based build practices might encounter issues with newer `cysignals` versions or Python packaging tooling.
Install
-
pip install cysignals
Imports
- sig_check
from cysignals.signals cimport sig_check
- sig_on
from cysignals.signals cimport sig_on
- sig_off
from cysignals.signals cimport sig_off
- sig_error
from cysignals.signals cimport sig_error
- changesignal
from cysignals.pysignals import changesignal
Quickstart
import cython
import os
# This code needs to be in a .pyx file to be compiled by Cython
# For demonstration, we simulate compilation by directly defining in Python context
# In a real scenario, this would be compiled with a setup.py/pyproject.toml
def run_interruptible_loop(n_iterations: int):
try:
# In a .pyx file, you would use: from cysignals.signals cimport sig_check
# For this quickstart, we use a mock for illustration in a .py file
# In practice, you'd compile this Cython code.
# This is a simplified representation of how sig_check would be used.
# Simulate Cython compilation and execution
print(f"Running a loop for {n_iterations} iterations. Try pressing CTRL+C.")
for i in range(n_iterations):
# Imagine this is within a Cython function containing a `sig_check()` call
if i % 1_000_000 == 0:
print(f" Iteration {i}")
# A real sig_check() would check for interrupts and raise KeyboardInterrupt
# if os.getenv('CYSIGNALS_SIMULATE_INTERRUPT') and i == n_iterations // 2:
# raise KeyboardInterrupt("Simulated interrupt")
# Simulate a small amount of work
_ = i * i
print("Loop completed without interruption.")
except KeyboardInterrupt:
print("\nLoop interrupted by user (KeyboardInterrupt caught)!")
except Exception as e:
print(f"An unexpected error occurred: {e}")
if __name__ == '__main__':
# This part would run the compiled Cython module
# For this example, we directly call the Python function simulating the loop.
run_interruptible_loop(10_000_000)