diff --git a/Lib/multiprocessing/connection.py b/Lib/multiprocessing/connection.py index e5694e3587e..fbbd5d91d39 100644 --- a/Lib/multiprocessing/connection.py +++ b/Lib/multiprocessing/connection.py @@ -497,6 +497,8 @@ if sys.platform != 'win32': ''' if duplex: s1, s2 = socket.socketpair() + s1.setblocking(True) + s2.setblocking(True) c1 = Connection(s1.detach()) c2 = Connection(s2.detach()) else: @@ -561,6 +563,7 @@ class SocketListener(object): if os.name == 'posix': self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self._socket.setblocking(True) self._socket.bind(address) self._socket.listen(backlog) self._address = self._socket.getsockname() @@ -579,6 +582,7 @@ class SocketListener(object): def accept(self): s, self._last_accepted = self._socket.accept() + s.setblocking(True) return Connection(s.detach()) def close(self): @@ -593,6 +597,7 @@ def SocketClient(address): ''' family = address_type(address) with socket.socket( getattr(socket, family) ) as s: + s.setblocking(True) s.connect(address) return Connection(s.detach()) diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py index f6f4f73952d..afb0bee4198 100644 --- a/Lib/test/test_multiprocessing.py +++ b/Lib/test/test_multiprocessing.py @@ -3312,9 +3312,43 @@ class TestFlags(unittest.TestCase): child_flags, grandchild_flags = json.loads(data.decode('ascii')) self.assertEqual(child_flags, grandchild_flags) +# +# Test interaction with socket timeouts - see Issue #6056 +# + +class TestTimeouts(unittest.TestCase): + @classmethod + def _test_timeout(cls, child, address): + time.sleep(1) + child.send(123) + child.close() + conn = multiprocessing.connection.Client(address) + conn.send(456) + conn.close() + + def test_timeout(self): + old_timeout = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(0.1) + parent, child = multiprocessing.Pipe(duplex=True) + l = multiprocessing.connection.Listener(family='AF_INET') + p = multiprocessing.Process(target=self._test_timeout, + args=(child, l.address)) + p.start() + child.close() + self.assertEqual(parent.recv(), 123) + parent.close() + conn = l.accept() + self.assertEqual(conn.recv(), 456) + conn.close() + l.close() + p.join(10) + finally: + socket.setdefaulttimeout(old_timeout) + testcases_other = [OtherTest, TestInvalidHandle, TestInitializers, TestStdinBadfiledescriptor, TestWait, TestInvalidFamily, - TestFlags] + TestFlags, TestTimeouts] # # diff --git a/Misc/ACKS b/Misc/ACKS index fc08cad25b7..a76e8421997 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1130,6 +1130,7 @@ John Williams Sue Williams Frank Willison Greg V. Wilson +J Derek Wilson Jody Winston Collin Winter Dik Winter diff --git a/Misc/NEWS b/Misc/NEWS index 2035f484aee..cf0d170b7fd 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -55,6 +55,9 @@ Core and Builtins Library ------- +- Issue #6056: Make multiprocessing use setblocking(True) on the + sockets it uses. Original patch by J Derek Wilson. + - Issue #15364: Fix sysconfig.get_config_var('srcdir') to be an absolute path.