agronholm / agronholm/anyio

CancelledError leaks from connect_tcp happy eyeballs on Python 3.14

Abierto
#1,094 8 comentarios 0 reacciones 0 asignados Ver en GitHub
bug
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

Abrir la 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

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.