Issue #9792: In case of connection failure, socket.create_connection()
would swallow the exception and raise a new one, making it impossible to fetch the original errno, or to filter timeout errors. Now the original error is re-raised.
This commit is contained in:
parent
a88c83cbab
commit
4b92b5fad3
|
@ -297,8 +297,8 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
|
|||
An host of '' or port 0 tells the OS to use the default.
|
||||
"""
|
||||
|
||||
msg = "getaddrinfo returns an empty list"
|
||||
host, port = address
|
||||
err = None
|
||||
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
|
||||
af, socktype, proto, canonname, sa = res
|
||||
sock = None
|
||||
|
@ -311,9 +311,12 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
|
|||
sock.connect(sa)
|
||||
return sock
|
||||
|
||||
except error as err:
|
||||
msg = err
|
||||
except error as _:
|
||||
err = _
|
||||
if sock is not None:
|
||||
sock.close()
|
||||
|
||||
raise error(msg)
|
||||
if err is not None:
|
||||
raise err
|
||||
else:
|
||||
raise error("getaddrinfo returns an empty list")
|
||||
|
|
|
@ -13,6 +13,7 @@ import queue
|
|||
import sys
|
||||
import os
|
||||
import array
|
||||
import contextlib
|
||||
from weakref import proxy
|
||||
import signal
|
||||
|
||||
|
@ -1203,12 +1204,42 @@ class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest):
|
|||
|
||||
class NetworkConnectionNoServer(unittest.TestCase):
|
||||
|
||||
def testWithoutServer(self):
|
||||
class MockSocket(socket.socket):
|
||||
def connect(self, *args):
|
||||
raise socket.timeout('timed out')
|
||||
|
||||
@contextlib.contextmanager
|
||||
def mocked_socket_module(self):
|
||||
"""Return a socket which times out on connect"""
|
||||
old_socket = socket.socket
|
||||
socket.socket = self.MockSocket
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
socket.socket = old_socket
|
||||
|
||||
def test_connect(self):
|
||||
port = support.find_unused_port()
|
||||
self.assertRaises(
|
||||
socket.error,
|
||||
lambda: socket.create_connection((HOST, port))
|
||||
)
|
||||
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
with self.assertRaises(socket.error) as cm:
|
||||
cli.connect((HOST, port))
|
||||
self.assertEqual(cm.exception.errno, errno.ECONNREFUSED)
|
||||
|
||||
def test_create_connection(self):
|
||||
# Issue #9792: errors raised by create_connection() should have
|
||||
# a proper errno attribute.
|
||||
port = support.find_unused_port()
|
||||
with self.assertRaises(socket.error) as cm:
|
||||
socket.create_connection((HOST, port))
|
||||
self.assertEqual(cm.exception.errno, errno.ECONNREFUSED)
|
||||
|
||||
def test_create_connection_timeout(self):
|
||||
# Issue #9792: create_connection() should not recast timeout errors
|
||||
# as generic socket errors.
|
||||
with self.mocked_socket_module():
|
||||
with self.assertRaises(socket.timeout):
|
||||
socket.create_connection((HOST, 1234))
|
||||
|
||||
|
||||
@unittest.skipUnless(thread, 'Threading required for this test.')
|
||||
class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
|
||||
|
|
|
@ -13,6 +13,11 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #9792: In case of connection failure, socket.create_connection()
|
||||
would swallow the exception and raise a new one, making it impossible
|
||||
to fetch the original errno, or to filter timeout errors. Now the
|
||||
original error is re-raised.
|
||||
|
||||
- Issue #9758: When fcntl.ioctl() was called with mutable_flag set to True,
|
||||
and the passed buffer was exactly 1024 bytes long, the buffer wouldn't
|
||||
be updated back after the system call. Original patch by Brian Brazil.
|
||||
|
|
Loading…
Reference in New Issue