agronholm / agronholm/anyio

CancelledError leaks from connect_tcp happy eyeballs on Python 3.14

Offen
#1,094 8 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
bug
Vorherrschende Sprache
Python
Sterne
2.5k
Forks
260
Ø Merge
1 T. 8 Std.
Gemergte PRs (30 T.)
17

Beschreibung

### Things to check first

- [x] I have searched the existing issues and didn't find my bug already reported there

- [x] I have checked that my bug is still present in the latest release

### AnyIO version

4.12.1

### Python version

3.14.2

### What happened?

When `connect_tcp` resolves a host with multiple addresses (A or AAAA records), the happy eyeballs algorithm races multiple `try_connect` subtasks and
cancels the losers via cancel scope. On Python 3.14, the `CancelledError` from cancelled subtasks leaks out of the task group instead of being caught
internally.

Expected: `connect_tcp` returns the winning connection and silently cancels the others.
Actual: `CancelledError` propagates to the caller.

This does not happen on Python 3.13 with the same code and dependencies.

### How can we reproduce the bug?

- Requires: httpcore (uses anyio's connect_tcp internally)
- Python 3.14.2, anyio 4.12.1
- The target host MUST resolve to multiple addresses (A or AAAA records) to trigger the happy eyeballs race. A single-address host won't reproduce it.

```
import asyncio
import httpcore

async def main():
pool = httpcore.AsyncConnectionPool()
try:
# Replace with any host that resolves to multiple A/AAAA records
response = await pool.request("GET", "https://your-multi-address-host.example.com/")
print(response.status)
finally:
await pool.aclose()

asyncio.run(main())
```

Traceback:
asyncio.exceptions.CancelledError: Cancelled via cancel scope ... by
.try_connect() running at anyio/_core/_sockets.py:189>
cb=[TaskGroup._spawn..task_done() at anyio/_backends/_asyncio.py:805]>

Beitragsleitfaden

Beitragsleitfaden öffnen

Bewertung

Dieses Issue wurde noch nicht bewertet.

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.