channels: Disconnect() method of WebSocketConsumer not being called

I have the following MyConsumer class:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
import json

class MyConsumer(WebsocketConsumer):
   
       def connect(self):
          self.accept()
       
       def receive(self, text_data=None, bytes_data=None):
          data = json.loads(text_data)
          n = data["number"]
          
          for i in range(n):
              self.send(json.dumps({"number":i}))
              
       def disconnect(self, code):
           raise StopConsumer()

The input JSON contains only a single parameter called number. I am testing this code using a chrome plugin. When I open the connection and close it without sending any message, the disconnect method is executed as expected.

When the number is for example 100000 and the loop inside the receive method is not yet finished and I disconnect in between, the disconnect method is not called and I get the following error:

ERROR - server - Exception inside application: Attempt to send on a closed protocol.
File "MyConsumer.py", line 2, in receive
    self.send
File "python3.6/site-packages/channels/generic/websocket.py", line 69, in send
    {"type": "websocket.send", "text": text_data},
  File "python3.6/site-packages/channels/consumer.py", line 107, in send
    self.base_send(message)
  File "python3.6/site-packages/asgiref/sync.py", line 64, in __call__
    return call_result.result()
  File "/usr/local/var/pyenv/versions/3.6.10/lib/python3.6/concurrent/futures/_base.py", line 432, in result
    return self.__get_result()
  File "/usr/local/var/pyenv/versions/3.6.10/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
    result = await self.awaitable(*args, **kwargs)
  File "python3.6/site-packages/channels/sessions.py", line 220, in send
    return await self.real_send(message)
  File "python3.6/site-packages/daphne/server.py", line 198, in handle_reply
    protocol.handle_reply(message)
  File "python3.6/site-packages/daphne/ws_protocol.py", line 179, in handle_reply
    self.serverSend(message["text"], False)
  File "site-packages/daphne/ws_protocol.py", line 223, in serverSend
    self.sendMessage(content.encode("utf8"), binary)
  File "python3.6/site-packages/autobahn/websocket/protocol.py", line 2216, in sendMessage
    raise Disconnected("Attempt to send on a closed protocol")
  Attempt to send on a closed protocol
OS: Mac OS X
runtime: python 3.6.10
daphne==2.2.0
Django==2.0.6
channels==2.1.1
channels-redis==2.2.1

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 7
  • Comments: 15 (8 by maintainers)

Most upvoted comments

Same issue for AsyncWebsocketConsumer.

Issue caused by a recent change in autobahn: https://autobahn.readthedocs.io/en/latest/changelog.html#id17

fix: WebSocket protocol instances now raise autobahn.exception.Disconnected when sending on a closed connection (#1002) https://github.com/crossbario/autobahn-python/issues/1002

Possible solution by subclassing AsyncWebsocketConsumer (channels/generic/websocket.py):

    async def send(self, *args, **kwargs):
        try:
            await super().send(*args, **kwargs)
        except autobahn.exception.Disconnected:
            await self.close()

@wynshiter The cause of the disconnects themselves is probably out of scope for this issue, and you might get a better response with a new issue, detailing the Django+Channels versions you’re using, the clients, example code, etc.

Just to be sure: after the Attempt to send on a closed protocol, are you seeing the same behaviour as reported in the opening post: the disconnect() handler is not executed for that connection? And is this output from the devserver?

Some pointers for your troubleshooting: one of the most common causes for periodic WS disconnects is the client failing to send pongs back to the server (though that shouldn’t cause the Attempt to send... message you’re seeing), or the webserver or proxy such as nginx or haproxy having a timeout that’s smaller than the ping/pong interval – but that’s unlikely here given the 127.0.0.1 address. Is your client a browser or someting else? Are you sure there’s nothing on the client side dropping the connection?

A failing test demonstrating the issue, and then the fix, would be appreciated here.