aio-libs / aio-libs/aiomcache

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

Đang mở
#489 2 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Python
Star
158
Fork
41
Merge trung bình
1 phút
Pull request đã merge (30 ngày)
1

Mô tả

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
```

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.