Python 2.6 added a
siginterrupt()
function to the signal module , so that you can deal with the
EINTR
problem . Unfortunately it doesn't necessarily do what you want, because of CPython signal handler semantics .
(Ob-attribution:
signal.siginterrupt()
was brought to my attention by a commentator on the
EINTR
entry .)
What you probably want when you combine
siginterrupt()
and a signal handler, and what a lot of people probably think that they are getting, is that when your program is sitting in a system call and gets a signal, your signal handler function gets called and does its thing while the system call just keeps going, none the wiser. (This is what happens in C, more or less.)
What you get instead is that processing the signal is deferred until the system call completes . Your program is sitting in a system call, gets a signal, and (as far as your Python code is concerned) absolutely nothing happens until the system call completes, whenever that is. Only then does your signal handler function wake up and do its thing.
This happens because CPython only runs Python signal handler functions when control returns to the bytecode interpreter. System calls failing with
EINTR
is the brute force mechanism that normally causes this to happen relatively soon after your program gets a signal; the program gets a signal, the system call fails with
EINTR
, the C code making the system call notices this and raises an exception, which returns control to the bytecode interpreter. When system calls don't get
EINTR
any more, the whole chain of events stops (well, never gets started) and there you are, waiting for the system call to finish normally.
One might hope that Python's
siginterrupt()
does something clever to get around this, but it doesn't; it is strictly a wrapper for the C library
siginterrupt(3)
function. (It probably has to be, since I think that doing otherwise would require C module API changes.)
There are probably situations and signal handlers where this is acceptable, or at least the least worst choice, but I do think that it makes
siginterrupt()
a lot less useful than it first appears.
(I also think that this should be explicitly mentioned in the
siginterrupt()
description, although you can work it out from the current documentation if you put all of the pieces together.)