Message 102725 - Python tracker (original) (raw)

The effect of signal.siginterrupt(somesig, False) is reset the first time a that signal is received. This is not the documented behaviour, and I do not think this is a desireable behaviour. It renders siginterrupt effectively useless at providing the robustness against EINTR it is intended to provide.

Actually, siginterrupt shouldn't be used. The proper way is to use sigaction with SA_RESTART flag (and still, don't rely on SA_RESTART too much, certain syscalls are non restartable and this isn't realy portable).

Another might be to not call PyOS_setsig from signal_handler at all -- I'm not sure why it is trying to reinstall itself, but perhaps there's some issue there I'm not aware of.

Because signal.signal might be implemented with sigaction() or signal() and the latter resets the default signal handler when the handler is called. This means that if your system doesn't support sigaction and and you don't reinstall it, then the handler will only get called the first time. However, reinstalling the signal handler contains a race, because if a second signal comes before you reinstall it, it's handled by the default handler. That's why sigaction is much better (and calling PyOS_setsig unecessary when sigaction is available).

The problem you describe can happen with both sigaction and signal :

sigaction:

signal:

So the simple fix when sigaction is available is simply to not call PyOS_setsig() from signal_handler. When sigaction is not available, well, you have to recall that you want restartable syscalls, and call siginterrupt again with that value. But I think if the OS doesn't support sigaction, there's little chance it'll support siginterrupt. (1) I just found out that Windows doesn't have sigaction, but I don't know Window much, so if someone could confirm that it doesn't support siginterrupt, then the fix would simply be to not reinstall handler when sigaction is available.