[Python-Dev] Questions about signal handling.

Eric Snow ericsnowcurrently at gmail.com
Fri Sep 21 19:01:45 EDT 2018

Hi all,

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 [1]
(written in 1994):

   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.


[1] https://github.com/python/cpython/blob/master/Modules/signalmodule.c#L71

More information about the Python-Dev mailing list