
Nathaniel Smith wrote:
So what should this async_signals_masked state do when we yield out from under it? If it's a thread-local, then the masking state will "leak" into other async function callstacks (or similar for regular generators), which is pretty bad. But it can't be just frame-local data either, because we want the masking state to be inherited by and subroutines we call from inside the masked block.
That should be easy enough, shouldn't it? When entering a new frame, copy the mask state from the calling frame.
For example, we could have a flag on a function frame that says "this frame (and the code in it) should not be interrupted", and then in the bytecode loop when a signal arrives, walk up the call stack to see if any of these flags are set before running the Python-level signal handler.
That would make it impossible to temporarily unmask async signals in a region where they're masked. An example of a situation where you might want to do that is in an implementation of lock.acquire(). If the thread needs to block while waiting for the lock to become available, you probably want to allow ctrl-C to interrupt the thread while it's blocked.
This would make me nervous, because context managers are used for all kinds of things, and only some of them involve delicate resource manipulation.
The next step I had in mind was to extend the context manager protocol so that the context manager can indicate whether it wants async signals masked, so it would only happen for things like lock that really need it. -- Greg