Here's another case where this bug bites us: https://github.com/python-trio/trio/issues/673
At startup, Trio checks if SIGINT is currently being handled by Python's default SIGINT handler, and if so it substitutes its own SIGINT handler (which works just like the default SIGINT handler, except with some added magic [1]).
However, this user has a C library that installs its own handler for SIGINT. When this happens, the Python signal.getsignal() function returns stale, incorrect information (claiming that the Python signal handler is still working, even though it isn't), and this causes Trio to do the wrong thing.
Vilya's "magic cookie" approach above is the one that I was going to suggest before I saw this bug :-).
Jeroen's version seems more complicated than necessary to me, and also it doesn't seem to work for my case: I need to check what the current signal handler is and make some decision based on that result. In Jeroen's API, I can see what the Python-level signal handler is, but there's no way to find out whether that signal handler is actually in use or not. Instead, we should make signal.getsignal() do something like:
c_handler = PyOS_getsig(signalnum);
if c_handler == the_python_signal_handler:
# Python is handling this signal; return the Python-level handler
return Handlers[signalnum].func
elif c_handler in [SIG_DFL, SIG_IGN]:
return c_handler
else:
return OpaqueCookie(c_handler)
[1] https://vorpus.org/blog/control-c-handling-in-python-and-trio/