aio-libs / aio-libs/aiomcache

Connection returned to pool in inconsistent state when `asyncio.CancelledError` occurs

Abierto
#489 2 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
158
Forks
41
Merge medio
1 min
PR fusionados (30 d)
1

Descripción

I encountered an issue in the `acquire` decorator where a connection may be returned to the pool in an inconsistent state.

This happens because `asyncio.CancelledError` inherits from `BaseException`, not from `Exception`. As a result, it is not caught by the `except Exception` block.

Relevant code:
[https://github.com/aio-libs/aiomcache/blob/master/aiomcache/client.py#L28](https://github.com/aio-libs/aiomcache/blob/master/aiomcache/client.py#L28)

Because of this, when a coroutine is cancelled, `conn[0].set_exception(exc)` is not called before `self._pool.release(conn)`.

As a result, a broken connection can be returned to the pool and reused later, which may lead to errors like:

```
ValueError: Separator is not found, and chunk exceed the limit
```

This can be fixed by explicitly handling `asyncio.CancelledError` and marking the connection as failed before returning it to the pool.

Example:

```python
def acquire(
func: Callable[Concatenate[_Client, Connection, _P], Awaitable[_T]]
) -> Callable[Concatenate[_Client, _P], Awaitable[_T]]:

@functools.wraps(func)
async def wrapper(self: _Client, *args: _P.args, # type: ignore[misc]
**kwargs: _P.kwargs) -> _T:
conn = await self._pool.acquire()
try:
return await func(self, conn, *args, **kwargs)
except Exception as exc:
conn[0].set_exception(exc)
raise
except asyncio.CancelledError as exc:
# Got CancelledError from client code.
conn[0].set_exception(exc)
raise
finally:
self._pool.release(conn)

return wrapper
```

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.