Python, signal handlers, and
One of the interesting effects of setting a signal handler in your Python program is, well, let me quote the signal module:
- When a signal arrives during an I/O operation, it is possible that the I/O operation raises an exception after the signal handler returns. This is dependent on the underlying Unix system's semantics regarding interrupted system calls.
By 'an I/O operation' the manual means more than you might think; for
select.select() is affected by this. (This is where the
whole socket error boondoggle becomes very
In general, on Unixes that behave this way, signals that are handled
during 'slow' operations (especially IO-related ones) normally cause
the system call to fail with an
EINTR error. Which system calls this
affects and under what circumstances is system dependent, but you
generally can count on it affecting at least socket operations, talking
to the user's terminal, and things like
(And some system calls don't fail with
EINTR but instead return
partial results if, for example, they have already transmitted part of
write() on a socket.)
When CPython sees that a system call failed, it raises an exception. It
pretty much doesn't do anything special when
EINTR is the 'failure'
reason; you still get a Python level exception, and it is up to you to
notice that this failure is not really a failure and you should retry
the operation, assuming that you can and want to.
(There are cases where you cannot; for example, I believe that
socket.sendall() can be hit with an
EINTR despite having sent some
of the buffer, at which point you get an exception instead of a partial
It is my personal feeling that given Python's rich exception handling,
your low-level Python code should always retry operations when you get
EINTR-based exception. If a signal handler actually wants to abort
or redirect the program, it can easily do this by raising an appropriate
exception; in the mean time, your low-level code is in the best position
to retry the aborted system call.
On Unixes that have
EINTR, you can usually tell the kernel that
you actually don't want your system calls interrupted just because a
particular signal handler got called by setting the
flag on the signal handler. Unfortunately, Python does not expose
this, even on systems that support it.
Somewhat to my surprise, the GNU libc texinfo documentation has a decent
discussion of signals,