[pypy-commit] pypy stdlib-2.7.6: handle eintr in multiprocessing

bdkearns noreply at buildbot.pypy.org
Tue Mar 4 02:21:09 CET 2014


Author: Brian Kearns <bdkearns at gmail.com>
Branch: stdlib-2.7.6
Changeset: r69648:69c907ade980
Date: 2014-03-03 20:19 -0500
http://bitbucket.org/pypy/pypy/changeset/69c907ade980/

Log:	handle eintr in multiprocessing

diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -1,4 +1,5 @@
 import sys
+from errno import EINTR
 
 from rpython.rlib import rpoll, rsocket
 from rpython.rlib.rarithmetic import intmask
@@ -306,6 +307,9 @@
             try:
                 count = self.WRITE(data)
             except OSError, e:
+                if e.errno == EINTR:
+                    space.getexecutioncontext().checksignals()
+                    continue
                 raise wrap_oserror(space, e)
             size -= count
             message = rffi.ptradd(message, count)
@@ -317,6 +321,9 @@
             try:
                 data = self.READ(remaining)
             except OSError, e:
+                if e.errno == EINTR:
+                    space.getexecutioncontext().checksignals()
+                    continue
                 raise wrap_oserror(space, e)
             count = len(data)
             if count == 0:
@@ -340,10 +347,8 @@
 
     def do_poll(self, space, timeout):
         if not self._check_fd():
-            raise OperationError(space.w_IOError, space.wrap(
-                "handle out of range in select()"))
-
-        r, w, e = rpoll.select([self.fd], [], [], timeout)
+            raise oefmt(space.w_IOError, "handle out of range in select()")
+        r, w, e = rpoll.select([self.fd], [], [], timeout, handle_eintr=True)
         return bool(r)
 
 W_FileConnection.typedef = TypeDef(
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -1,4 +1,3 @@
-
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.tool import rffi_platform as platform
@@ -40,7 +39,7 @@
                      'net/if.h')
 
     cond_includes = [('AF_NETLINK', 'linux/netlink.h')]
-    
+
     libraries = ()
     calling_conv = 'c'
     HEADER = ''.join(['#include <%s>\n' % filename for filename in includes])
@@ -612,11 +611,11 @@
 
     WSAPROTOCOL_INFO = cConfig.WSAPROTOCOL_INFO
     FROM_PROTOCOL_INFO = cConfig.FROM_PROTOCOL_INFO
-    WSADuplicateSocket = external('WSADuplicateSocketA', 
+    WSADuplicateSocket = external('WSADuplicateSocketA',
                                   [socketfd_type, rwin32.DWORD,
                                    lltype.Ptr(WSAPROTOCOL_INFO)],
                                   rffi.INT)
-    WSASocket = external('WSASocketA', 
+    WSASocket = external('WSASocketA',
                          [rffi.INT, rffi.INT, rffi.INT,
                           lltype.Ptr(WSAPROTOCOL_INFO),
                           rwin32.DWORD, rwin32.DWORD],
diff --git a/rpython/rlib/rpoll.py b/rpython/rlib/rpoll.py
--- a/rpython/rlib/rpoll.py
+++ b/rpython/rlib/rpoll.py
@@ -5,6 +5,7 @@
 function that directly takes a dictionary as argument.
 """
 
+from errno import EINTR
 from rpython.rlib import _rsocket_rffi as _c
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rtyper.lltypesystem import lltype, rffi
@@ -71,9 +72,9 @@
             lltype.free(pollfds, flavor='raw')
         return retval
 
-def select(inl, outl, excl, timeout=-1.0):
+def select(inl, outl, excl, timeout=-1.0, handle_eintr=False):
     nfds = 0
-    if inl: 
+    if inl:
         ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw')
         _c.FD_ZERO(ll_inl)
         for i in inl:
@@ -82,7 +83,7 @@
                 nfds = i
     else:
         ll_inl = lltype.nullptr(_c.fd_set.TO)
-    if outl: 
+    if outl:
         ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw')
         _c.FD_ZERO(ll_outl)
         for i in outl:
@@ -91,7 +92,7 @@
                 nfds = i
     else:
         ll_outl = lltype.nullptr(_c.fd_set.TO)
-    if excl: 
+    if excl:
         ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw')
         _c.FD_ZERO(ll_excl)
         for i in excl:
@@ -100,15 +101,23 @@
                 nfds = i
     else:
         ll_excl = lltype.nullptr(_c.fd_set.TO)
-    if timeout != -1.0:
+
+    if timeout < 0:
+        ll_timeval = lltype.nullptr(_c.timeval)
+        while True:
+            res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval)
+            if not handle_eintr or res >= 0 or _c.geterrno() != EINTR:
+                break
+    else:
+        sec = int(timeout)
+        usec = int((timeout - sec) * 10**6)
         ll_timeval = rffi.make(_c.timeval)
-        rffi.setintfield(ll_timeval, 'c_tv_sec', int(timeout))
-        rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-int(timeout))
-                                                  * 1000000))
-    else:
-        ll_timeval = lltype.nullptr(_c.timeval)
+        rffi.setintfield(ll_timeval, 'c_tv_sec', sec)
+        rffi.setintfield(ll_timeval, 'c_tv_usec', usec)
+        res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval)
+        if handle_eintr and res < 0 and _c.geterrno() == EINTR:
+            res = 0  # interrupted, act as timed out
     try:
-        res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval)
         if res == -1:
             raise SelectError(_c.geterrno())
         if res == 0:


More information about the pypy-commit mailing list