Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-raise OSError as ClientConnectionError when failing to explicitly close connector socket #10551

Merged
merged 4 commits into from
Mar 16, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/10551.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The connector now raises :exc:`aiohttp.ClientConnectionError` instead of :exc:`OSError` when failing to explicitly close the socket after :py:meth:`asyncio.loop.create_connection` fails -- by :user:`bdraco`.
5 changes: 4 additions & 1 deletion aiohttp/connector.py
Original file line number Diff line number Diff line change
@@ -1143,7 +1143,10 @@ async def _wrap_create_connection(
# Will be hit if an exception is thrown before the event loop takes the socket.
# In that case, proactively close the socket to guard against event loop leaks.
# For example, see https://github.com/MagicStack/uvloop/issues/653.
sock.close()
try:
sock.close()
except OSError as exc:
raise client_error(req.connection_key, exc) from exc

def _warn_about_tls_in_tls(
self,
27 changes: 27 additions & 0 deletions tests/test_connector.py
Original file line number Diff line number Diff line change
@@ -669,6 +669,33 @@ async def test_tcp_connector_closes_socket_on_error(
await conn.close()


async def test_tcp_connector_closes_socket_on_error_results_in_another_error(
loop: asyncio.AbstractEventLoop, start_connection: mock.AsyncMock
) -> None:
"""Test that when error occurs while closing the socket."""
req = ClientRequest("GET", URL("https://127.0.0.1:443"), loop=loop)
start_connection.return_value.close.side_effect = OSError(
1, "error from closing socket"
)

conn = aiohttp.TCPConnector()
with (
mock.patch.object(
conn._loop,
"create_connection",
autospec=True,
spec_set=True,
side_effect=ValueError,
),
pytest.raises(aiohttp.ClientConnectionError, match="error from closing socket"),
):
await conn.connect(req, [], ClientTimeout())

assert start_connection.return_value.close.called

await conn.close()


async def test_tcp_connector_server_hostname_default(
loop: asyncio.AbstractEventLoop, start_connection: mock.AsyncMock
) -> None: