Branch merge
diff --git a/Lib/ssl.py b/Lib/ssl.py
index 1b7416e..914e749 100644
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -355,14 +355,6 @@
         else:
             return socket.sendto(self, data, flags_or_addr, addr)
 
-    def sendmsg(self, *args, **kwargs):
-        self._checkClosed()
-        if self._sslobj:
-            raise ValueError("sendmsg not allowed on instances of %s" %
-                             self.__class__)
-        else:
-            return socket.sendmsg(self, *args, **kwargs)
-
     def sendall(self, data, flags=0):
         self._checkClosed()
         if self._sslobj:
@@ -421,22 +413,6 @@
         else:
             return socket.recvfrom_into(self, buffer, nbytes, flags)
 
-    def recvmsg(self, *args, **kwargs):
-        self._checkClosed()
-        if self._sslobj:
-            raise ValueError("recvmsg not allowed on instances of %s" %
-                             self.__class__)
-        else:
-            return socket.recvmsg(self, *args, **kwargs)
-
-    def recvmsg_into(self, *args, **kwargs):
-        self._checkClosed()
-        if self._sslobj:
-            raise ValueError("recvmsg_into not allowed on instances of %s" %
-                             self.__class__)
-        else:
-            return socket.recvmsg_into(self, *args, **kwargs)
-
     def pending(self):
         self._checkClosed()
         if self._sslobj:
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index 214e430..ca63496 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -577,7 +577,6 @@
         elif ok == FAILED:
             bad.append(test)
         elif ok == ENV_CHANGED:
-            bad.append(test)
             environment_changed.append(test)
         elif ok == SKIPPED:
             skipped.append(test)
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
index 405fbd5..7a7805d 100644
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -35,7 +35,7 @@
 import multiprocessing.heap
 import multiprocessing.pool
 
-from multiprocessing import util
+from multiprocessing import util, reduction
 
 try:
     from multiprocessing.sharedctypes import Value, copy
@@ -43,6 +43,11 @@
 except ImportError:
     HAS_SHAREDCTYPES = False
 
+try:
+    import msvcrt
+except ImportError:
+    msvcrt = None
+
 #
 #
 #
@@ -89,6 +94,11 @@
             timeout = None
         return handle in _select([handle], [], [], timeout)[0]
 
+try:
+    MAXFD = os.sysconf("SC_OPEN_MAX")
+except:
+    MAXFD = 256
+
 #
 # Some tests require ctypes
 #
@@ -1587,6 +1597,76 @@
 
         self.assertRaises(ValueError, a.send_bytes, msg, 4, -1)
 
+    @classmethod
+    def _is_fd_assigned(cls, fd):
+        try:
+            os.fstat(fd)
+        except OSError as e:
+            if e.errno == errno.EBADF:
+                return False
+            raise
+        else:
+            return True
+
+    @classmethod
+    def _writefd(cls, conn, data, create_dummy_fds=False):
+        if create_dummy_fds:
+            for i in range(0, 256):
+                if not cls._is_fd_assigned(i):
+                    os.dup2(conn.fileno(), i)
+        fd = reduction.recv_handle(conn)
+        if msvcrt:
+            fd = msvcrt.open_osfhandle(fd, os.O_WRONLY)
+        os.write(fd, data)
+        os.close(fd)
+
+    def test_fd_transfer(self):
+        if self.TYPE != 'processes':
+            self.skipTest("only makes sense with processes")
+        conn, child_conn = self.Pipe(duplex=True)
+
+        p = self.Process(target=self._writefd, args=(child_conn, b"foo"))
+        p.start()
+        with open(test.support.TESTFN, "wb") as f:
+            fd = f.fileno()
+            if msvcrt:
+                fd = msvcrt.get_osfhandle(fd)
+            reduction.send_handle(conn, fd, p.pid)
+        p.join()
+        with open(test.support.TESTFN, "rb") as f:
+            self.assertEqual(f.read(), b"foo")
+
+    @unittest.skipIf(sys.platform == "win32",
+                     "test semantics don't make sense on Windows")
+    @unittest.skipIf(MAXFD <= 256,
+                     "largest assignable fd number is too small")
+    @unittest.skipUnless(hasattr(os, "dup2"),
+                         "test needs os.dup2()")
+    def test_large_fd_transfer(self):
+        # With fd > 256 (issue #11657)
+        if self.TYPE != 'processes':
+            self.skipTest("only makes sense with processes")
+        conn, child_conn = self.Pipe(duplex=True)
+
+        p = self.Process(target=self._writefd, args=(child_conn, b"bar", True))
+        p.start()
+        with open(test.support.TESTFN, "wb") as f:
+            fd = f.fileno()
+            for newfd in range(256, MAXFD):
+                if not self._is_fd_assigned(newfd):
+                    break
+            else:
+                self.fail("could not find an unassigned large file descriptor")
+            os.dup2(fd, newfd)
+            try:
+                reduction.send_handle(conn, newfd, p.pid)
+            finally:
+                os.close(newfd)
+        p.join()
+        with open(test.support.TESTFN, "rb") as f:
+            self.assertEqual(f.read(), b"bar")
+
+
 class _TestListenerClient(BaseTestCase):
 
     ALLOWED_TYPES = ('processes', 'threads')
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index 1d26c11..f3f0c54 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -186,11 +186,8 @@
         self.assertRaises(socket.error, ss.recv_into, bytearray(b'x'))
         self.assertRaises(socket.error, ss.recvfrom, 1)
         self.assertRaises(socket.error, ss.recvfrom_into, bytearray(b'x'), 1)
-        self.assertRaises(socket.error, ss.recvmsg, 1)
-        self.assertRaises(socket.error, ss.recvmsg_into, [bytearray(b'x')])
         self.assertRaises(socket.error, ss.send, b'x')
         self.assertRaises(socket.error, ss.sendto, b'x', ('0.0.0.0', 0))
-        self.assertRaises(socket.error, ss.sendmsg, [b'x'])
 
     def test_timeout(self):
         # Issue #8524: when creating an SSL socket, the timeout of the
@@ -1523,30 +1520,17 @@
                     count, addr = s.recvfrom_into(b)
                     return b[:count]
 
-                def _recvmsg(*args, **kwargs):
-                    return s.recvmsg(*args, **kwargs)[0]
-
-                def _recvmsg_into(bufsize, *args, **kwargs):
-                    b = bytearray(bufsize)
-                    return bytes(b[:s.recvmsg_into([b], *args, **kwargs)[0]])
-
-                def _sendmsg(msg, *args, **kwargs):
-                    return s.sendmsg([msg])
-
                 # (name, method, whether to expect success, *args)
                 send_methods = [
                     ('send', s.send, True, []),
                     ('sendto', s.sendto, False, ["some.address"]),
-                    ('sendmsg', _sendmsg, False, []),
                     ('sendall', s.sendall, True, []),
                 ]
                 recv_methods = [
                     ('recv', s.recv, True, []),
                     ('recvfrom', s.recvfrom, False, ["some.address"]),
-                    ('recvmsg', _recvmsg, False, [100]),
                     ('recv_into', _recv_into, True, []),
                     ('recvfrom_into', _recvfrom_into, False, []),
-                    ('recvmsg_into', _recvmsg_into, False, [100]),
                 ]
                 data_prefix = "PREFIX_"
 
diff --git a/Misc/ACKS b/Misc/ACKS
index 062a77a..e734608 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -748,6 +748,7 @@
 Michael Piotrowski
 Antoine Pitrou
 Jean-François Piéronne
+Remi Pointel
 Guilherme Polo
 Michael Pomraning
 Iustin Pop
diff --git a/Misc/NEWS b/Misc/NEWS
index b2d9e84..4b5a9a6 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -268,6 +268,9 @@
 Library
 -------
 
+- Issue #11657: Fix sending file descriptors over 255 over a multiprocessing
+  Pipe.
+
 - Issue #12811: tabnanny.check() now promptly closes checked files. Patch by
   Anthony Briggs.
 
diff --git a/Modules/_multiprocessing/multiprocessing.c b/Modules/_multiprocessing/multiprocessing.c
index 5d1cf56..1987b95 100644
--- a/Modules/_multiprocessing/multiprocessing.c
+++ b/Modules/_multiprocessing/multiprocessing.c
@@ -111,7 +111,7 @@
     cmsg->cmsg_type = SCM_RIGHTS;
     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
     msg.msg_controllen = cmsg->cmsg_len;
-    *CMSG_DATA(cmsg) = fd;
+    * (int *) CMSG_DATA(cmsg) = fd;
 
     Py_BEGIN_ALLOW_THREADS
     res = sendmsg(conn, &msg, 0);
@@ -154,7 +154,7 @@
     if (res < 0)
         return PyErr_SetFromErrno(PyExc_OSError);
 
-    fd = *CMSG_DATA(cmsg);
+    fd = * (int *) CMSG_DATA(cmsg);
     return Py_BuildValue("i", fd);
 }
 
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 81d1ce1..5878ebb 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -156,6 +156,10 @@
 # undef HAVE_GETHOSTBYNAME_R_6_ARG
 #endif
 
+#if defined(__OpenBSD__)
+# include <sys/uio.h>
+#endif
+
 #ifndef WITH_THREAD
 # undef HAVE_GETHOSTBYNAME_R
 #endif