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.
|
An host of '' or port 0 tells the OS to use the default.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
msg = "getaddrinfo returns an empty list"
|
|
||||||
host, port = address
|
host, port = address
|
||||||
|
err = None
|
||||||
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
|
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
|
||||||
af, socktype, proto, canonname, sa = res
|
af, socktype, proto, canonname, sa = res
|
||||||
sock = None
|
sock = None
|
||||||
|
@ -311,9 +311,12 @@ def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
|
||||||
sock.connect(sa)
|
sock.connect(sa)
|
||||||
return sock
|
return sock
|
||||||
|
|
||||||
except error as err:
|
except error as _:
|
||||||
msg = err
|
err = _
|
||||||
if sock is not None:
|
if sock is not None:
|
||||||
sock.close()
|
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 sys
|
||||||
import os
|
import os
|
||||||
import array
|
import array
|
||||||
|
import contextlib
|
||||||
from weakref import proxy
|
from weakref import proxy
|
||||||
import signal
|
import signal
|
||||||
|
|
||||||
|
@ -1203,12 +1204,42 @@ class BasicTCPTest2(NetworkConnectionTest, BasicTCPTest):
|
||||||
|
|
||||||
class NetworkConnectionNoServer(unittest.TestCase):
|
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()
|
port = support.find_unused_port()
|
||||||
self.assertRaises(
|
cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
socket.error,
|
with self.assertRaises(socket.error) as cm:
|
||||||
lambda: socket.create_connection((HOST, port))
|
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.')
|
@unittest.skipUnless(thread, 'Threading required for this test.')
|
||||||
class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
|
class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest):
|
||||||
|
|
|
@ -13,6 +13,11 @@ Core and Builtins
|
||||||
Library
|
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,
|
- 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
|
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.
|
be updated back after the system call. Original patch by Brian Brazil.
|
||||||
|
|
Loading…
Reference in New Issue