Python interface to signal handlers¶
In this module, we distinguish between the “OS-level” signal handler and the “Python-level” signal handler.
The Python function signal.signal()
sets both of these: it sets
the Python-level signal handler to the function specified by the user.
It also sets the OS-level signal handler to a specific C function
which calls the Python-level signal handler.
The Python signal
module does not allow access to the OS-level
signal handler (in particular, it does not allow one to temporarily change
a signal handler if the OS-level handler was not the Python one).
-
class
cysignals.pysignals.
SigAction
¶ An opaque object representing an OS-level signal handler.
The only legal initializers are
signal.SIG_DFL
(the default),signal.SIG_IGN
and anotherSigAction
object (which is copied).EXAMPLES:
>>> from cysignals.pysignals import SigAction >>> SigAction() <SigAction with sa_handler=SIG_DFL> >>> import signal >>> SigAction(signal.SIG_DFL) <SigAction with sa_handler=SIG_DFL> >>> SigAction(signal.SIG_IGN) <SigAction with sa_handler=SIG_IGN> >>> A = SigAction(signal.SIG_IGN) >>> SigAction(A) <SigAction with sa_handler=SIG_IGN> >>> SigAction(A) == A True
TESTS:
>>> SigAction(42) Traceback (most recent call last): ... TypeError: cannot initialize SigAction from <... 'int'>
-
class
cysignals.pysignals.
changesignal
(sig, action)¶ Context to temporarily change a signal handler.
This should be used as follows:
with changesignal(sig, action): ...
Inside the context, code behaves as if
signal.signal(sig, action)
was called. When leaving the context, the signal handler is restored to what it was before. Both the Python-level and OS-level signal handlers are restored.EXAMPLES:
>>> from cysignals.pysignals import changesignal >>> import os, signal >>> def handler(*args): print("got signal") >>> _ = signal.signal(signal.SIGQUIT, signal.SIG_IGN) >>> with changesignal(signal.SIGQUIT, handler): ... os.kill(os.getpid(), signal.SIGQUIT) got signal >>> os.kill(os.getpid(), signal.SIGQUIT) >>> with changesignal(signal.SIGQUIT, handler): ... setossignal(signal.SIGQUIT, signal.SIG_DFL) ... raise Exception("just testing") Traceback (most recent call last): ... Exception: just testing >>> os.kill(os.getpid(), signal.SIGQUIT)
-
cysignals.pysignals.
getossignal
(sig)¶ Get the OS-level signal handler.
This returns an opaque object of type
SigAction
which can only be used in a future call tosetossignal()
.EXAMPLES:
>>> from cysignals.pysignals import getossignal >>> import signal >>> getossignal(signal.SIGINT) <SigAction with sa_handler=0x...> >>> getossignal(signal.SIGUSR1) <SigAction with sa_handler=SIG_DFL> >>> def handler(*args): pass >>> _ = signal.signal(signal.SIGUSR1, handler) >>> getossignal(signal.SIGUSR1) <SigAction with sa_handler=0x...>
TESTS:
>>> getossignal(None) Traceback (most recent call last): ... TypeError: an integer is required >>> getossignal(-1) Traceback (most recent call last): ... OSError: [Errno 22] Invalid argument
-
cysignals.pysignals.
setossignal
(sig, action)¶ Set the OS-level signal handler to
action
, which should either besignal.SIG_DFL
orsignal.SIG_IGN
or aSigAction
object returned by an earlier call togetossignal()
orsetossignal()
.Return the old signal handler.
EXAMPLES:
>>> from cysignals.pysignals import setossignal >>> import os, signal >>> def handler(*args): print("got signal") >>> _ = signal.signal(signal.SIGHUP, handler) >>> os.kill(os.getpid(), signal.SIGHUP) got signal >>> pyhandler = setossignal(signal.SIGHUP, signal.SIG_IGN) >>> pyhandler <SigAction with sa_handler=0x...> >>> os.kill(os.getpid(), signal.SIGHUP) >>> setossignal(signal.SIGHUP, pyhandler) <SigAction with sa_handler=SIG_IGN> >>> os.kill(os.getpid(), signal.SIGHUP) got signal >>> setossignal(signal.SIGHUP, signal.SIG_DFL) == pyhandler True
TESTS:
>>> setossignal(signal.SIGHUP, None) Traceback (most recent call last): ... TypeError: cannot initialize SigAction from <... 'NoneType'> >>> setossignal(-1, signal.SIG_DFL) Traceback (most recent call last): ... OSError: [Errno 22] Invalid argument
-
cysignals.pysignals.
setsignal
(sig, action, osaction=None)¶ Set the Python-level signal handler for signal
sig
toaction
. Ifosaction
is given, set the OS-level signal handler toosaction
. Ifosaction
isNone
(the default), change only the Python-level handler and keep the OS-level handler.Return the old Python-level handler.
EXAMPLES:
>>> from cysignals.pysignals import * >>> def handler(*args): print("got signal") >>> _ = signal.signal(signal.SIGSEGV, handler) >>> A = getossignal(signal.SIGILL) >>> _ = setsignal(signal.SIGILL, getsignal(signal.SIGSEGV)) >>> getossignal(signal.SIGILL) == A True >>> _ = setossignal(signal.SIGILL, getossignal(signal.SIGSEGV)) >>> import os >>> os.kill(os.getpid(), signal.SIGILL) got signal >>> setsignal(signal.SIGILL, signal.SIG_DFL) <function handler at 0x...> >>> _ = setsignal(signal.SIGALRM, signal.SIG_DFL, signal.SIG_IGN) >>> os.kill(os.getpid(), signal.SIGALRM) >>> _ = setsignal(signal.SIGALRM, handler, getossignal(signal.SIGSEGV)) >>> os.kill(os.getpid(), signal.SIGALRM) got signal
TESTS:
>>> setsignal(-1, signal.SIG_DFL) Traceback (most recent call last): ... OSError: [Errno 22] Invalid argument