[pypy-commit] pypy py3.5-eintr-pep475: pep475ify the socket objects

arigo pypy.commits at gmail.com
Sun Dec 4 14:15:11 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5-eintr-pep475
Changeset: r88880:dbc5c6b1041f
Date: 2016-12-04 20:14 +0100
http://bitbucket.org/pypy/pypy/changeset/dbc5c6b1041f/

Log:	pep475ify the socket objects

diff --git a/pypy/module/_socket/interp_socket.py b/pypy/module/_socket/interp_socket.py
--- a/pypy/module/_socket/interp_socket.py
+++ b/pypy/module/_socket/interp_socket.py
@@ -1,5 +1,6 @@
-import sys
+import sys, errno
 from rpython.rlib import rsocket, rweaklist
+from rpython.rlib.objectmodel import specialize
 from rpython.rlib.rarithmetic import intmask
 from rpython.rlib.rsocket import (
     RSocket, AF_INET, SOCK_STREAM, SocketError, SocketErrorWithErrno,
@@ -227,12 +228,13 @@
         representing the connection, and the address of the client.
         For IP sockets, the address info is a pair (hostaddr, port).
         """
-        try:
-            fd, addr = self.sock.accept(inheritable=False)
-            return space.newtuple([space.wrap(fd),
-                                   addr_as_object(addr, fd, space)])
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                fd, addr = self.sock.accept(inheritable=False)
+                return space.newtuple([space.wrap(fd),
+                                       addr_as_object(addr, fd, space)])
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
 
     # convert an Address into an app-level object
     def addr_as_object(self, space, address):
@@ -274,10 +276,12 @@
         Connect the socket to a remote address.  For IP sockets, the address
         is a pair (host, port).
         """
-        try:
-            self.sock.connect(self.addr_from_object(space, w_addr))
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                self.sock.connect(self.addr_from_object(space, w_addr))
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
 
     def connect_ex_w(self, space, w_addr):
         """connect_ex(address) -> errno
@@ -289,7 +293,11 @@
             addr = self.addr_from_object(space, w_addr)
         except SocketError as e:
             raise converted_error(space, e)
-        error = self.sock.connect_ex(addr)
+        while True:
+            error = self.sock.connect_ex(addr)
+            if error != errno.EINTR:
+                break
+            space.getexecutioncontext().checksignals()
         return space.wrap(error)
 
     def fileno_w(self, space):
@@ -384,10 +392,12 @@
         at least one byte is available or until the remote end is closed.  When
         the remote end is closed and all data is read, return the empty string.
         """
-        try:
-            data = self.sock.recv(buffersize, flags)
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                data = self.sock.recv(buffersize, flags)
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
         return space.newbytes(data)
 
     @unwrap_spec(buffersize='nonnegint', flags=int)
@@ -396,15 +406,17 @@
 
         Like recv(buffersize, flags) but also return the sender's address info.
         """
-        try:
-            data, addr = self.sock.recvfrom(buffersize, flags)
-            if addr:
-                w_addr = addr_as_object(addr, self.sock.fd, space)
-            else:
-                w_addr = space.w_None
-            return space.newtuple([space.newbytes(data), w_addr])
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                data, addr = self.sock.recvfrom(buffersize, flags)
+                if addr:
+                    w_addr = addr_as_object(addr, self.sock.fd, space)
+                else:
+                    w_addr = space.w_None
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
+        return space.newtuple([space.newbytes(data), w_addr])
 
     @unwrap_spec(data='bufferstr', flags=int)
     def send_w(self, space, data, flags=0):
@@ -414,10 +426,12 @@
         argument, see the Unix manual.  Return the number of bytes
         sent; this may be less than len(data) if the network is busy.
         """
-        try:
-            count = self.sock.send(data, flags)
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                count = self.sock.send(data, flags)
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
         return space.wrap(count)
 
     @unwrap_spec(data='bufferstr', flags=int)
@@ -450,11 +464,13 @@
             # 3 args version
             flags = space.int_w(w_param2)
             w_addr = w_param3
-        try:
-            addr = self.addr_from_object(space, w_addr)
-            count = self.sock.sendto(data, flags, addr)
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                addr = self.addr_from_object(space, w_addr)
+                count = self.sock.sendto(data, flags, addr)
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
         return space.wrap(count)
 
     @unwrap_spec(flag=int)
@@ -520,10 +536,13 @@
         lgt = rwbuffer.getlength()
         if nbytes == 0 or nbytes > lgt:
             nbytes = lgt
-        try:
-            return space.wrap(self.sock.recvinto(rwbuffer, nbytes, flags))
-        except SocketError as e:
-            raise converted_error(space, e)
+        while True:
+            try:
+                nbytes_read = self.sock.recvinto(rwbuffer, nbytes, flags)
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
+        return space.wrap(nbytes_read)
 
     @unwrap_spec(nbytes=int, flags=int)
     def recvfrom_into_w(self, space, w_buffer, nbytes=0, flags=0):
@@ -538,15 +557,20 @@
         elif nbytes > lgt:
             raise oefmt(space.w_ValueError,
                         "nbytes is greater than the length of the buffer")
-        try:
-            readlgt, addr = self.sock.recvfrom_into(rwbuffer, nbytes, flags)
-            if addr:
+        while True:
+            try:
+                readlgt, addr = self.sock.recvfrom_into(rwbuffer, nbytes, flags)
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
+        if addr:
+            try:
                 w_addr = addr_as_object(addr, self.sock.fd, space)
-            else:
-                w_addr = space.w_None
-            return space.newtuple([space.wrap(readlgt), w_addr])
-        except SocketError as e:
-            raise converted_error(space, e)
+            except SocketError as e:
+                raise converted_error(space, e)
+        else:
+            w_addr = space.w_None
+        return space.newtuple([space.wrap(readlgt), w_addr])
 
     @unwrap_spec(cmd=int)
     def ioctl_w(self, space, cmd, w_option):
@@ -690,15 +714,20 @@
 def get_error(space, name):
     return space.fromcache(SocketAPI).get_exception(name)
 
-def converted_error(space, e):
+ at specialize.arg(2)
+def converted_error(space, e, eintr_retry=False):
     message = e.get_msg()
     w_exception_class = get_error(space, e.applevelerrcls)
     if isinstance(e, SocketErrorWithErrno):
+        if e.errno == errno.EINTR:
+            space.getexecutioncontext().checksignals()
+            if eintr_retry:
+                return       # only return None if eintr_retry==True
         w_exception = space.call_function(w_exception_class, space.wrap(e.errno),
                                       space.wrap(message))
     else:
         w_exception = space.call_function(w_exception_class, space.wrap(message))
-    return OperationError(w_exception_class, w_exception)
+    raise OperationError(w_exception_class, w_exception)
 
 # ____________________________________________________________
 


More information about the pypy-commit mailing list