[Python-Dev] Questions about signal handling.
ericsnowcurrently at gmail.com
Fri Sep 21 19:01:45 EDT 2018
I've got a pretty good sense of how signal handling works in the
runtime (i.e. via a dance with the eval loop), but still have some
1. Why do we restrict calls to signal.signal() to the main thread?
2. Why must signal handlers run in the main thread?
3. Why does signal handling operate via the "pending calls" machinery
and not distinctly?
More details are below. My interest in the topic relates to improving
in-process interpreter isolation.
#1 & #2
Toward the top of signalmodule.c we find the following comment 
(written in 1994):
NOTES ON THE INTERACTION BETWEEN SIGNALS AND THREADS
When threads are supported, we want the following semantics:
- only the main thread can set a signal handler
- any thread can get a signal handler
- signals are only delivered to the main thread
I.e. we don't support "synchronous signals" like SIGFPE (catching
this doesn't make much sense in Python anyway) nor do we support
signals as a means of inter-thread communication, since not all
thread implementations support that (at least our thread library
We still have the problem that in some implementations signals
generated by the keyboard (e.g. SIGINT) are delivered to all
threads (e.g. SGI), while in others (e.g. Solaris) such signals are
delivered to one random thread (an intermediate possibility would
be to deliver it to the main thread -- POSIX?). For now, we have
a working implementation that works in all three cases -- the
handler ignores signals if getpid() isn't the same as in the main
thread. XXX This is a hack.
At the very top of the file we see another relevant comment:
/* XXX Signals should be recorded per thread, now we have thread state. */
That one was written in 1997, right after PyThreadState was introduced.
So is the constraint about the main thread just a historical artifact?
If not, what would be an appropriate explanation for why signals must
be strictly bound to the main thread?
Regarding the use of Py_MakePendingCalls() for signal handling, I can
imagine the history there. However, is there any reason signal
handling couldn't be separated from the "pending calls" machinery at
this point? As far as I can tell there is no longer any strong
relationship between the two.
More information about the Python-Dev