aio-libs / aio-libs/aiohttp

WebSocketResponse requires closing/closed checks before sending something

未关闭
#3,391 3 条评论 1 个 reaction 已指派 0 人 在 GitHub 查看
bug
主要语言
Python
星标
16.5k
派生
2.4k
平均合并
17 小时 22 分钟
30 天内合并 PR
212

描述

## Long story short

In the server-side websocket handlers written with aiohttp, `WebSocketResponse`'s `send_xxx()` methods "ignores" closing/closed state of the connection.

So in my code, I had to add `if ws.closed: break` everywhere that calls `send_xxx()`.

Maybe this issue is related to #2025.

## Expected behaviour

The `send_xxx()` methods should raise an explicit exception so that a server-side task can notice if the connection is closed.

## Actual behaviour

The `send_xxx()` methods just emit an warning to the logger and continue.
This behavior leads to a memory leak as the unsent messages accumulates in the buffer.
I get a stream of log messages like:
```
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
websocket connection is closing.
socket.send() raised exception.
...
```
until my server-side task finishes (which runs without noticing the connection is closed!).

## Steps to reproduce

1. Write a simple websocket handler like:

```python
async def handler(request):
ws = web.WebSocketResponse()
await ws.prepare(request)
for _ in range(10):
await asyncio.sleep(1)
await ws.send_str('test')
return ws
```

2. Open this handler in a web browser using Javascript that reads only one message and closes the connection actively.
(NOTE: closing the page abruptly in the browser makes aiohttp to raise `asyncio.CancelledError`)

## Your environment

Linux & macOS.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。