[Python-Dev] RFC: PEP 475, Retry system calls failing with EINTR

R. David Murray rdmurray at bitdance.com
Mon Sep 1 06:51:25 CEST 2014

On Sun, 31 Aug 2014 20:14:50 -0700, Dan Stromberg <drsalists at gmail.com> wrote:
> On Sun, Aug 31, 2014 at 3:28 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> > Victor Stinner wrote:
> >>
> >> As written in the PEP, if you want to be notified of the signal, set a
> >> signal handler which raises an exception.
> >
> > I'm not convinced that this covers all possible use cases.
> > It might be all right if you have control over the signal
> > handler, but what if you don't?
> >
> > I think it's best if the functions in the os module remain
> > thin wrappers that expose the OS functionality as fully and
> > directly as possible. Anything else should be provided
> > by higher-level facilities.
> I'm inclined to agree about keeping the os module thin.  If we were to
> recreate Python today, from scratch, it might make sense to hide this
> by default, but now there's almost certainly code out there that
> depends on the current behavior.
> But I also agree that it's hard to pin down which higher level Python
> library calls are going to be using system calls.  My
> http://stromberg.dnsalias.org/~strombrg/pypty/ program had a problem
> with window resizing for a while (SIGWINCH), and although I use it
> pretty much daily now without problems, I'm still not sure I got 100%
> of the possibilities covered.
> Fortunately, wrapping a system call can be as simple as:
> def retry_on_eintr(function, *args, **kw):
>     '''
>     Retry a system call until one of the following happens:
>     1) It succeeds
>     2) It errors with something other than EINTR
>     '''
>     while True:
>         try:
>             return function(*args, **kw)
>         except OSError:
>             nothing, extra, nothing2 = sys.exc_info()
>             dummy = nothing
>             dummy = nothing2
>             if extra.errno == errno.EINTR:
>                 continue
>             else:
>                 raise
> Note that os.read() and os.write() need different handling.

Personally, I really want Python to handle EINTR for me.  And indeed,
that has been what we have been doing for a while now, piece by piece,
bug by bug.  Victor just wants to systematize and document that, and I
think that's a good idea.

We've been consistently treating lack of handling of EINTR as a bug.
If there are *real* cases where that causes a backward compatibility
problem, then we need to know.  But so far, we have gotten zero
complaints about the cases that we have fixed.


PS: I recently switched from using selectors to using a timeout on a
socket because in that particular application I could, and because
reading a socket with a timeout handles EINTR (in recent python
versions), whereas reading a non-blocking socket doesn't.  Under the
hood, a socket with a timeout is a non-blocking socket.

More information about the Python-Dev mailing list