[pypy-commit] pypy py3.5-sendmsg-recvmsg: Fix for the test_EINTR errors on sendmsg and recvmsg

Dodan pypy.commits at gmail.com
Tue Aug 1 09:12:58 EDT 2017


Author: Dodan Mihai <mihai.dodan at gmail.com>
Branch: py3.5-sendmsg-recvmsg
Changeset: r92014:a8d5fdebbce7
Date: 2017-08-01 16:11 +0300
http://bitbucket.org/pypy/pypy/changeset/a8d5fdebbce7/

Log:	Fix for the test_EINTR errors on sendmsg and recvmsg

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
@@ -473,27 +473,27 @@
             raise oefmt(space.w_ValueError, "negative buffer size in recvmsg()")
         if ancbufsize < 0:
             raise oefmt(space.w_ValueError, "invalid ancillary data buffer length")
-        try:
-            tuple = self.sock.recvmsg(message_size, ancbufsize, flags)
-            message = space.newbytes(tuple[0])
-            # print(tuple[0])
-            list = []
-            for l in tuple[1]:
-                tup = space.newtuple([space.newint(l[0]), space.newint(l[1]), space.newbytes(l[2])])
-                list.append(tup)
+        while True:
+            try:
+                tuple = self.sock.recvmsg(message_size, ancbufsize, flags)
+                message = space.newbytes(tuple[0])
+                list = []
+                for l in tuple[1]:
+                    tup = space.newtuple([space.newint(l[0]), space.newint(l[1]), space.newbytes(l[2])])
+                    list.append(tup)
 
-            anc = space.newlist(list)
+                anc = space.newlist(list)
 
-            flag = space.newint(tuple[2])
-            if (tuple[3] is not None):
-                address = addr_as_object(tuple[3], self.sock.fd, space)
-            else:
-                address = space.w_None
-
-            rettup = space.newtuple([message, anc, flag, address])
-            return rettup
-        except SocketError as e:
-            converted_error(space, e, eintr_retry=True)
+                flag = space.newint(tuple[2])
+                if (tuple[3] is not None):
+                    address = addr_as_object(tuple[3], self.sock.fd, space)
+                else:
+                    address = space.w_None
+                rettup = space.newtuple([message, anc, flag, address])
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
+        return rettup
 
     @unwrap_spec(data='bufferstr', flags=int)
     def send_w(self, space, data, flags=0):
@@ -566,110 +566,117 @@
         :return: Bytes sent from the message
         """
         # Get the flag and address from the object space
-        flags = 0
-        if space.is_none(w_flags) is False:
-            flags = space.int_w(w_flags)
+        while True:
+            try:
+                flags = 0
+                if space.is_none(w_flags) is False:
+                    flags = space.int_w(w_flags)
 
-        address = None
-        if space.is_none(w_address) is False:
-            address = self.addr_from_object(space, w_address)
+                address = None
+                if space.is_none(w_address) is False:
+                    address = self.addr_from_object(space, w_address)
 
-        # find data's type in the ObjectSpace and get a list of string out of it.
-        data = []
-        if (w_data.typedef.name == 'list'):
-            for i in w_data.getitems():
-                if space.isinstance_w(i,space.w_bytes):
-                    data.append(space.bytes_w(i))
+                # find data's type in the ObjectSpace and get a list of string out of it.
+                data = []
+                if (w_data.typedef.name == 'list'):
+                    for i in w_data.getitems():
+                        if space.isinstance_w(i, space.w_bytes):
+                            data.append(space.bytes_w(i))
+                        else:
+                            if (i.typedef.name == 'array.array'):
+                                data.append(space.bytes_w(i.descr_tobytes(space)))
+                            else:
+                                if (i.typedef.name == 'memoryview'):
+                                    data.append(space.bytes_w(i.descr_tobytes(space)))
+                                else:
+                                    raise oefmt(space.w_TypeError, "a bytes-like object is required")
                 else:
-                    if (i.typedef.name == 'array.array'):
-                        data.append(space.bytes_w(i.descr_tobytes(space)))
+                    while True:
+                        try:
+                            if (space.is_generator(w_data) is False):
+                                raise oefmt(space.w_TypeError, "sendmsg(): argument 1 must be iterable")
+                            i = space.next(w_data)
+                            if space.isinstance_w(i, space.w_bytes):
+                                data.append(space.bytes_w(i))
+                            else:
+                                if (i.typedef.name == 'array.array'):
+                                    data.append(space.bytes_w(i.descr_tobytes(space)))
+                                else:
+                                    if (i.typedef.name == 'memoryview'):
+                                        data.append(space.bytes_w(i.descr_tobytes(space)))
+                                    else:
+                                        raise oefmt(space.w_TypeError, "a bytes-like object is required")
+                        except OperationError as e:
+                            if not e.match(space, space.w_StopIteration):
+                                raise
+                            break
+
+                # find the ancillary's type in the ObjectSpace and get a list of tuples out of it.
+                ancillary = []
+                if w_ancillary is not None:
+                    if (space.isinstance_w(w_ancillary, space.w_list)):
+                        for i in w_ancillary.getitems():
+                            if (space.isinstance_w(i, space.w_tuple) is False):
+                                raise oefmt(space.w_TypeError, "[sendmsg() ancillary data items]() argument must be sequence")
+                            if (space.len_w(i) == 3):
+                                level = space.int_w(space.getitem(i, space.newint(0)))
+                                type = space.int_w(space.getitem(i, space.newint(1)))
+                                if (space.getitem(i, space.newint(2)).typedef.name == 'array.array'):
+                                    cont = space.bytes_w(space.getitem(i, space.newint(2)).descr_tobytes(space))
+                                else:
+                                    if (space.isinstance_w(space.getitem(i, space.newint(2)), space.w_bytes)):
+                                        cont = space.bytes_w(space.getitem(i, space.newint(2)))
+                                    else:
+                                        raise oefmt(space.w_TypeError, "a bytes-like object is required")
+                                tup = (level, type, cont)
+                                ancillary.append(tup)
+                            else:
+                                raise oefmt(space.w_TypeError,
+                                            "[sendmsg() ancillary data items]() argument must be sequence of length 3")
+
                     else:
-                        raise oefmt(space.w_TypeError, "a bytes-like object is required")
-        else:
-            while True:
-                try:
-                    if (space.is_generator(w_data) is False):
-                        raise oefmt(space.w_TypeError, "sendmsg(): argument 1 must be iterable")
-                    i = space.next(w_data)
-                    if space.isinstance_w(i, space.w_bytes):
-                        data.append(space.bytes_w(i))
-                    else:
-                        if (i.typedef.name == 'array.array'):
-                            data.append(space.bytes_w(i.descr_tobytes(space)))
-                        else:
-                            raise oefmt(space.w_TypeError, "a bytes-like object is required")
-                except OperationError as e:
-                    if not e.match(space,space.w_StopIteration):
-                        raise
-                    break
+                        while True:
+                            try:
+                                if (space.is_generator(w_ancillary) is False):
+                                    raise oefmt(space.w_TypeError,
+                                                "[sendmsg() ancillary data items]() argument must be sequence")
+                                i = space.next(w_ancillary)
+                                if (space.isinstance_w(i, space.w_tuple) is False):
+                                    raise oefmt(space.w_TypeError,
+                                                "[sendmsg() ancillary data items]() argument must be sequence of length 3")
+                                if (space.len_w(i) != 3):
+                                    raise oefmt(space.w_TypeError,
+                                                "[sendmsg() ancillary data items]() argument must be sequence of length 3")
+                            except OperationError as e:
+                                if not e.match(space, space.w_StopIteration):
+                                    raise
+                                break
+                            level = space.int_w(space.getitem(i, space.newint(0)))
+                            type = space.int_w(space.getitem(i, space.newint(1)))
+                            if (space.getitem(i, space.newint(2)).typedef.name == 'array.array'):
+                                cont = space.bytes_w(space.getitem(i, space.newint(2)).descr_tobytes(space))
+                            else:
+                                if (space.isinstance_w(space.getitem(i, space.newint(2)), space.w_bytes)):
+                                    cont = space.bytes_w(space.getitem(i, space.newint(2)))
+                                else:
+                                    raise oefmt(space.w_TypeError, "a bytes-like object is required")
+                            tup = (level, type, cont)
+                            ancillary.append(tup)
 
-        # find the ancillary's type in the ObjectSpace and get a list of tuples out of it.
-        ancillary = []
-        if w_ancillary is not None:
-            if (space.isinstance_w(w_ancillary,space.w_list)):
-                for i in w_ancillary.getitems():
-                    if (space.isinstance_w(i, space.w_tuple) is False):
-                        raise oefmt(space.w_TypeError,"[sendmsg() ancillary data items]() argument must be sequence")
-                    if (space.len_w(i) == 3):
-                        level = space.int_w(space.getitem(i, space.newint(0)))
-                        type = space.int_w(space.getitem(i, space.newint(1)))
-                        if (space.getitem(i, space.newint(2)).typedef.name == 'array.array'):
-                            cont = space.bytes_w(space.getitem(i, space.newint(2)).descr_tobytes(space))
-                        else:
-                            if (space.isinstance_w(space.getitem(i, space.newint(2)), space.w_bytes)):
-                                cont = space.bytes_w(space.getitem(i, space.newint(2)))
-                            else:
-                                raise oefmt(space.w_TypeError,"a bytes-like object is required")
-                        tup = (level, type, cont)
-                        ancillary.append(tup)
-                    else:
-                        raise oefmt(space.w_TypeError,
-                                    "[sendmsg() ancillary data items]() argument must be sequence of length 3")
 
-            else:
-                while True:
-                    try:
-                        if (space.is_generator(w_ancillary) is False):
-                            raise oefmt(space.w_TypeError,
-                                        "[sendmsg() ancillary data items]() argument must be sequence")
-                        i = space.next(w_ancillary)
-                        if (space.isinstance_w(i, space.w_tuple) is False):
-                            raise oefmt(space.w_TypeError,
-                                        "[sendmsg() ancillary data items]() argument must be sequence of length 3")
-                        if (space.len_w(i) != 3):
-                            raise oefmt(space.w_TypeError,
-                                        "[sendmsg() ancillary data items]() argument must be sequence of length 3")
-                    except OperationError as e:
-                        if not e.match(space,space.w_StopIteration):
-                            raise
-                        break
-                    level = space.int_w(space.getitem(i, space.newint(0)))
-                    type = space.int_w(space.getitem(i, space.newint(1)))
-                    if (space.getitem(i, space.newint(2)).typedef.name == 'array.array'):
-                        cont = space.bytes_w(space.getitem(i, space.newint(2)).descr_tobytes(space))
-                    else:
-                        if (space.isinstance_w(space.getitem(i, space.newint(2)), space.w_bytes)):
-                            cont = space.bytes_w(space.getitem(i, space.newint(2)))
-                        else:
-                            raise oefmt(space.w_TypeError, "a bytes-like object is required")
-                    tup = (level, type, cont)
-                    ancillary.append(tup)
+                count = self.sock.sendmsg(data, ancillary, flags, address)
+                if count < 0:
+                    if (count == -1000):
+                        raise oefmt(space.w_OSError, "sending multiple control messages not supported")
+                    if (count == -1001):
+                        raise oefmt(space.w_OSError, "ancillary data item too large")
+                    if (count == -1002):
+                        raise oefmt(space.w_OSError, "too much ancillary data")
+                break
+            except SocketError as e:
+                converted_error(space, e, eintr_retry=True)
 
-        try:
-            count = self.sock.sendmsg(data, ancillary, flags, address)
-            if count < 0:
-                if (count == -1000):
-                    raise oefmt(space.w_OSError, "sending multiple control messages not supported")
-                if (count == -1001):
-                    raise oefmt(space.w_OSError, "ancillary data item too large")
-                if (count == -1002):
-                    raise oefmt(space.w_OSError, "too much ancillary data")
-
-            return space.newint(count)
-        except SocketError as e:
-            converted_error(space, e, eintr_retry=True)
-
-
+        return space.newint(count)
 
     @unwrap_spec(flag=int)
     def setblocking_w(self, flag):
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
@@ -514,15 +514,15 @@
                                   int flags,
                                   struct sockaddr* address,
                                   socklen_t* addrlen,
-                                  int** length_of_messages,
+                                  long** length_of_messages,
                                   char** messages,
-                                  int* no_of_messages,
-                                  int* size_of_ancillary,
+                                  long* no_of_messages,
+                                  long* size_of_ancillary,
                                   long** levels,
                                   long** types,
                                   char** file_descr,
                                   long** descr_per_ancillary,
-                                  int* retflag)
+                                  long* retflag)
 
         {
 
@@ -629,13 +629,15 @@
             *addrlen = retinfo->addrlen;
 
             // Set the parameters of message
-            *no_of_messages = retinfo->no_of_messages;
-            *size_of_ancillary = retinfo->size_of_ancillary;
-            *length_of_messages = (int*) malloc (sizeof(int) * retinfo->no_of_messages);
-            memcpy(*length_of_messages, retinfo->length_of_messages, sizeof(int) * retinfo->no_of_messages);
+            no_of_messages[0] = retinfo->no_of_messages;
+            size_of_ancillary[0] = retinfo->size_of_ancillary;
+            *length_of_messages = (long*) malloc (sizeof(long) * retinfo->no_of_messages);
+            //memcpy(*length_of_messages, retinfo->length_of_messages, sizeof(int) * retinfo->no_of_messages);
             int counter = 0;
-            for (i=0; i< retinfo->no_of_messages; i++)
+            for (i=0; i< retinfo->no_of_messages; i++){
                 counter += retinfo->length_of_messages[i];
+                length_of_messages[0][i] = retinfo->length_of_messages[i];
+            }
             memset(*messages, 0, sizeof(char) * counter);
             counter = 0;
             for(i=0; i< retinfo->no_of_messages; i++){
@@ -664,7 +666,7 @@
             }
 
             // Set the retflag
-            *retflag = retinfo->retflag;
+            retflag[0] = retinfo->retflag;
 
             // Free the memory
             free(retinfo->address);
@@ -959,7 +961,7 @@
     post_include_bits =[ "RPY_EXTERN "
                          "int sendmsg_implementation(int socket, struct sockaddr* address, socklen_t addrlen, long* length_of_messages, char** messages, int no_of_messages, long* levels, long* types, char** file_descriptors, long* no_of_fds, int control_length, int flag );\n"
                          "RPY_EXTERN "
-                         "int recvmsg_implementation(int socket_fd, int message_size, int ancillary_size, int flags, struct sockaddr* address, socklen_t* addrlen, int** length_of_messages, char** messages, int* no_of_messages, int* size_of_ancillary, long** levels, long** types, char** file_descr, long** descr_per_ancillary, int* flag);\n"
+                         "int recvmsg_implementation(int socket_fd, int message_size, int ancillary_size, int flags, struct sockaddr* address, socklen_t* addrlen, long** length_of_messages, char** messages, long* no_of_messages, long* size_of_ancillary, long** levels, long** types, char** file_descr, long** descr_per_ancillary, long* flag);\n"
                          "static "
                          "int cmsg_min_space(struct msghdr *msg, struct cmsghdr *cmsgh, size_t space);\n"
                          "static "
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -932,7 +932,6 @@
                     address.addrlen = addrlen
                 else:
                     address = None
-                print address
                 data = buf.str(read_bytes)
                 return (data, address)
         raise self.error_handler()
@@ -997,7 +996,7 @@
         retflag[0] = rffi.cast(rffi.SIGNED,0)
 
         # a mask for the SIGNEDP's that need to be cast to int. (long default)
-        LONG_MASK =  2**32 - 1
+        #LONG_MASK =  2**32 - 1
         reply = _c.recvmsg(self.fd, rffi.cast(lltype.Signed,message_size),
                            rffi.cast(lltype.Signed,ancbufsize),rffi.cast(lltype.Signed,flags),
                            addr_p, addrlen_p, len_of_msgs, messages, no_of_messages,size_of_anc,
@@ -1011,7 +1010,7 @@
 
             for i in range(msg_no):
                 x = rffi.cast(rffi.SIGNED,len_of_msgs[0][i])
-                x &= LONG_MASK
+                #x &= LONG_MASK
                 retmsg = rffi.charp2strn(messages[0],x)
 
             offset = 0
@@ -1078,6 +1077,8 @@
 
             if address is not None:
                 address.unlock()
+            if _c.geterrno() == _c.EINTR:
+                raise last_error()
             if (reply == -10000):
                 raise RSocketError("Invalid message size")
             if (reply == -10001):


More information about the pypy-commit mailing list