[pypy-commit] pypy py3k: Buffered IO should catch EINTR and retry.
amauryfa
noreply at buildbot.pypy.org
Tue Nov 22 22:18:41 CET 2011
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r49673:32c718fe8261
Date: 2011-11-14 07:57 +0100
http://bitbucket.org/pypy/pypy/changeset/32c718fe8261/
Log: Buffered IO should catch EINTR and retry.
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -11,12 +11,23 @@
W_IOBase, DEFAULT_BUFFER_SIZE, convert_size,
check_readable_w, check_writable_w, check_seekable_w)
from pypy.module._io.interp_io import W_BlockingIOError
+import errno
STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
class BlockingIOError(Exception):
pass
+def trap_EINTR(space, e):
+ """Return True if an EnvironmentError with errno == EINTR is set."""
+ if not e.match(space, space.w_EnvironmentError):
+ return False
+ w_value = e.get_w_value(space)
+ w_errno = space.getattr(w_value, space.wrap("errno"))
+ if space.eq_w(w_errno, space.wrap(errno.EINTR)):
+ return True
+ return False
+
class W_BufferedIOBase(W_IOBase):
def _unsupportedoperation(self, space, message):
w_exc = space.getattr(space.getbuiltinmodule('_io'),
@@ -315,7 +326,18 @@
def _write(self, space, data):
w_data = space.wrapbytes(data)
- w_written = space.call_method(self.w_raw, "write", w_data)
+ # NOTE: wrap_oserror() calls checksignals() when EINTR
+ # occurs so we needn't do it ourselves.
+ # We then retry writing, ignoring the signal if no handler has
+ # raised (see issue #10956).
+ while True:
+ try:
+ w_written = space.call_method(self.w_raw, "write", w_data)
+ break
+ except OperationError, e:
+ if trap_EINTR(space, e):
+ continue
+ raise
written = space.getindex_w(w_written, space.w_IOError)
if not 0 <= written <= len(data):
raise OperationError(space.w_IOError, space.wrap(
@@ -481,7 +503,18 @@
def _raw_read(self, space, buffer, start, length):
length = intmask(length)
w_buf = space.wrap(RawBuffer(buffer, start, length))
- w_size = space.call_method(self.w_raw, "readinto", w_buf)
+ # NOTE: wrap_oserror() calls checksignals() when EINTR
+ # occurs so we needn't do it ourselves.
+ # We then retry reading, ignoring the signal if no handler has
+ # raised (see issue #10956).
+ while True:
+ try:
+ w_size = space.call_method(self.w_raw, "readinto", w_buf)
+ break
+ except OperationError, e:
+ if trap_EINTR(space, e):
+ continue
+ raise
if space.is_w(w_size, space.w_None):
raise BlockingIOError()
size = space.int_w(w_size)
More information about the pypy-commit
mailing list