CancelledError leaks from connect_tcp happy eyeballs on Python 3.14
- Lenguaje dominante
- Python
- Estrellas
- 2.5k
- Forks
- 260
- Merge medio
- 2 d 8 h
- PR fusionados (30 d)
- 19
Descripción
### 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]>
Guía de contribución
Línea de trabajo
Start in anyio/_core/_sockets.py at connect_tcp and its try_connect task, using the traceback location as the entry point. Reproduce with Python 3.14.2, AnyIO 4.12.1, httpcore, and a host resolving to multiple addresses. Done means the winning connection is returned while cancelled loser tasks do not propagate CancelledError.
Escrito por el modelo de indexación a partir del texto del issue.
Evaluación
- Stack tecnológico
- python
- Área
- networking
- Tipo de issue
- Error
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Estado de actividad
- Tranquilo
- Claridad
- Bastante claro
- Aptitud para principiantes
- 62/100