Skip to content

WebSocketResponse requires closing/closed checks before sending something #3391

Open
@achimnol

Description

@achimnol

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:
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
  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions