mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
[3.14] gh-135836: Fix IndexError
in asyncio.create_connection
with empty exceptions list (GH-135845) (#136167)
gh-135836: Fix `IndexError` in `asyncio.create_connection` with empty exceptions list (GH-135845)
(cherry picked from commit 0e19db653d
)
Co-authored-by: heliang666s <147408835+heliang666s@users.noreply.github.com>
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
parent
b86d3f0d69
commit
8810ccfc60
3 changed files with 35 additions and 1 deletions
|
@ -1161,7 +1161,7 @@ class BaseEventLoop(events.AbstractEventLoop):
|
|||
raise ExceptionGroup("create_connection failed", exceptions)
|
||||
if len(exceptions) == 1:
|
||||
raise exceptions[0]
|
||||
else:
|
||||
elif exceptions:
|
||||
# If they all have the same str(), raise one.
|
||||
model = str(exceptions[0])
|
||||
if all(str(exc) == model for exc in exceptions):
|
||||
|
@ -1170,6 +1170,9 @@ class BaseEventLoop(events.AbstractEventLoop):
|
|||
# the various error messages.
|
||||
raise OSError('Multiple exceptions: {}'.format(
|
||||
', '.join(str(exc) for exc in exceptions)))
|
||||
else:
|
||||
# No exceptions were collected, raise a timeout error
|
||||
raise TimeoutError('create_connection failed')
|
||||
finally:
|
||||
exceptions = None
|
||||
|
||||
|
|
|
@ -1190,6 +1190,36 @@ class BaseEventLoopWithSelectorTests(test_utils.TestCase):
|
|||
self.loop.run_until_complete(coro)
|
||||
self.assertTrue(sock.close.called)
|
||||
|
||||
@patch_socket
|
||||
def test_create_connection_happy_eyeballs_empty_exceptions(self, m_socket):
|
||||
# See gh-135836: Fix IndexError when Happy Eyeballs algorithm
|
||||
# results in empty exceptions list
|
||||
|
||||
async def getaddrinfo(*args, **kw):
|
||||
return [(socket.AF_INET, socket.SOCK_STREAM, 0, '', ('127.0.0.1', 80)),
|
||||
(socket.AF_INET6, socket.SOCK_STREAM, 0, '', ('::1', 80))]
|
||||
|
||||
def getaddrinfo_task(*args, **kwds):
|
||||
return self.loop.create_task(getaddrinfo(*args, **kwds))
|
||||
|
||||
self.loop.getaddrinfo = getaddrinfo_task
|
||||
|
||||
# Mock staggered_race to return empty exceptions list
|
||||
# This simulates the scenario where Happy Eyeballs algorithm
|
||||
# cancels all attempts but doesn't properly collect exceptions
|
||||
with mock.patch('asyncio.staggered.staggered_race') as mock_staggered:
|
||||
# Return (None, []) - no winner, empty exceptions list
|
||||
async def mock_race(coro_fns, delay, loop):
|
||||
return None, []
|
||||
mock_staggered.side_effect = mock_race
|
||||
|
||||
coro = self.loop.create_connection(
|
||||
MyProto, 'example.com', 80, happy_eyeballs_delay=0.1)
|
||||
|
||||
# Should raise TimeoutError instead of IndexError
|
||||
with self.assertRaisesRegex(TimeoutError, "create_connection failed"):
|
||||
self.loop.run_until_complete(coro)
|
||||
|
||||
def test_create_connection_host_port_sock(self):
|
||||
coro = self.loop.create_connection(
|
||||
MyProto, 'example.com', 80, sock=object())
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix :exc:`IndexError` in :meth:`asyncio.loop.create_connection` that could occur when the Happy Eyeballs algorithm resulted in an empty exceptions list during connection attempts.
|
Loading…
Add table
Add a link
Reference in a new issue