Skip to main content

Modules/signalmodule.c

cpython 3.14 @ ab2d84fe1023/Modules/signalmodule.c

Modules/signalmodule.c implements signal. It registers C-level signal handlers with the OS and arranges for the Python handler to be called between bytecode instructions. The eval loop checks _Py_eval_breaker after each instruction; when a signal arrives, the C handler sets this flag.

Map

LinesSymbolRole
1-200signal_handler C function, _PySignal_AfterForkOS-level handler and fork cleanup
201-450signal_signal_impl, signal_getsignal_implPython API
451-650set_wakeup_fdWrite a byte to a pipe/socket on signal delivery
651-900raise_signal, pthread_kill wrapperSignal delivery helpers
901-1050Module initConstants: SIGINT, SIGTERM, SIG_DFL, SIG_IGN

Reading

Signal delivery to Python

The C signal handler cannot call Python directly (GIL may not be held). Instead it:

  1. Writes the signal number to Handlers[signum].func.
  2. Sets _Py_eval_breaker (an atomic flag).
  3. Optionally writes a byte to the wakeup fd.

Between bytecode instructions the eval loop checks _Py_eval_breaker; if set, it calls handle_signals which iterates Handlers[] and calls each registered Python callable.

set_wakeup_fd

set_wakeup_fd(fd) sets a non-blocking fd (typically the write end of a os.pipe() or a socket) that receives a single byte for each signal. This allows select()/poll() event loops to wake up on signals without polling.

# CPython: Modules/signalmodule.c:740 set_wakeup_fd_impl
# The fd must be non-blocking; a EAGAIN error is silently ignored.

SIGINT default handler

The default SIGINT handler raises KeyboardInterrupt in the main thread by setting _Py_HandlePending and InterruptOccurred.

gopy notes

Not yet ported. Signal handling in gopy will use os/signal.Notify to route signals to a Go channel, then convert them to KeyboardInterrupt or call registered Python handlers. Planned path: module/signal/.