question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Disconnect() method of WebSocketConsumer not being called

See original GitHub issue

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

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:6
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
carltongibsoncommented, Mar 26, 2021

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

1reaction
brubbelcommented, Mar 8, 2021

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()
Read more comments on GitHub >

github_iconTop Results From Across the Web

websocket - Disconnect() method of Django Channels ...
When we use WebsocketConsumer, the disconnect method will not be called until the current execution is not complete.
Read more >
Disconnect() method of Django Channels ...
When we use WebsocketConsumer, the disconnect method will not be called until the current execution is not complete. It is because of an...
Read more >
Consumers — Channels 4.0.0 documentation
DenyConnection from anywhere inside the connect method in order to accept or reject a connection, if you want reusable authentication or rate-limiting code...
Read more >
Testing Channels 2.0 consumers - problem with routing
There is a new error though, during disconnect, when calling this part of the test: await communicator.disconnect(). Here is disconnect method of my ......
Read more >
Channels Documentation - Read the Docs
async_to_sync is no longer needed when calling methods on the channel layer. Let's verify that the consumer for the /ws/chat/ROOM_NAME/ path ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found