This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author njs
Recipients Arfrever, Jim Fasarakis-Hilliard, Mark.Shannon, benjamin.peterson, cvrebert, daniel.urban, eric.snow, jcea, meador.inge, ncoghlan, njs, yselivanov
Date 2017-05-25.05:11:11
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1495689072.46.0.291223104786.issue12857@psf.upfronthosting.co.za>
In-reply-to
Content
> I'm not sure I understand how `f_func` would help to better handle Control-C in Trio. Nathaniel, could you please elaborate on that?

Sure. The issue is that I need to mark certain frames as "protected" from KeyboardInterrupt, in a way that my signal handler can see when walking the frame stack, so it can decide whether to raise a KeyboardInterrupt immediately or to wait until a safer moment. Right now, this is done by injecting a magic local variable into the frame object, so the code is effectively like:

def a_protected_function():
    _trio_keyboard_interrupt_protection_magic_local_ = True
    ... actual function ...

But this has two problems: (1) it's not atomic: a signal could arrive in between when the frame is created and when the magic local gets set. (This is especially a problem for __(a)exit__ methods -- if bpo-29988 is fixed then it will guarantee that __(a)exit__ gets called, but this isn't much help if __(a)exit__ can instantly abort without doing any actual cleanup :-).) (2) The decorator code for setting this magic local ends up having to special-case functions/generators/async functions/async generators, so it's very complex and fragile: https://github.com/python-trio/trio/blob/1586818fbdd5c3468e15b64816db9257adae49c1/trio/_core/_ki.py#L109-L149
(This is possibly the function that took the most tries to get right in all of trio, because there are serious subtleties and interactions with multiple CPython bugs.)

I suspect the way I'm currently munging frames at runtime also annoys PyPy's JIT.

OTOH if frames had f_func, then instead of having to munge frame.f_locals, I could set a magic attribute on the *functions* that are supposed to transition between protected/unprotected mode. Then I could delete all that nasty code and replace it with something like:

def enable_ki_protection(func):
    func._trio_keyboard_interrupt_protection_enabled = True
    return func

and in addition to being simpler, this would fix the race condition and improve performance too. (Note that now this decorator only runs at function definition time; I wouldn't have to do any tricky stuff at all during regular execution.)
History
Date User Action Args
2017-05-25 05:11:12njssetrecipients: + njs, jcea, ncoghlan, benjamin.peterson, Arfrever, cvrebert, meador.inge, daniel.urban, Mark.Shannon, eric.snow, yselivanov, Jim Fasarakis-Hilliard
2017-05-25 05:11:12njssetmessageid: <1495689072.46.0.291223104786.issue12857@psf.upfronthosting.co.za>
2017-05-25 05:11:12njslinkissue12857 messages
2017-05-25 05:11:11njscreate