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
-
Expected: The docs mention that the disconnect method should be called when the client closes the connection and an event is received (https://channels.readthedocs.io/en/latest/topics/consumers.html#closing-consumers). I expect that the disconnect method is called even if the loop is not finished yet.
-
I am running Channels using daphne.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 7
- Comments: 15 (8 by maintainers)
Same issue for AsyncWebsocketConsumer.
Issue caused by a recent change in autobahn: https://autobahn.readthedocs.io/en/latest/changelog.html#id17
Possible solution by subclassing AsyncWebsocketConsumer (channels/generic/websocket.py):
@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: thedisconnect()
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 asnginx
orhaproxy
having a timeout that’s smaller than the ping/pong interval – but that’s unlikely here given the127.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.