Open initzx opened 6 years ago
Having the same issue in conjunction with this library: https://github.com/graphql-python/graphql-ws
I created the websocket as follows:
ws = web.WebSocketResponse(protocols=('graphql-ws',), heartbeat=5, autoping=True)
I did some debugging. And when closing the connection from the client, I found out that the heartbeat cb _pong_not_received
was indeed called. However:
At aiohttp/web_ws.py:
def _pong_not_received(self):
if self._req is not None and self._req.transport is not None:
self._closed = True
self._close_code = 1006
self._exception = asyncio.TimeoutError()
self._req.transport.close()
The if statement did not go through. The underlying transport was already None. The way I see it, the websocket property closed
would never be set.
I did a small patch as follows:
@property
def closed(self):
return self._closed or self._req is None or self._req.transport is None
This made everything work on my end. However I don't fully understand all consequences of doing this, and the reasoning behind the current aproach.
@adaptivdesign In my case the connection was never meant to be closed. I have never requested the websocket to be closed so I do not understand why it would want to close itself on its own?
@initzx I assumed the socket.send() exception was because of a broken connection. I was having the same error, once a client disconnected, in which case the websocket did not close on the server end, and resulted in a socket.send() exception.
The logic in the patch helped me, thanks @adaptivdesign.
In my case I was able to easily reproduce this by having a mobile device(running android) connect to the websocket. Background the browser after the connection and wait a short while, this exception message would show in the logs but can not be caught.
Any update or a workaround without patching aiohttp directly?
BTW, this is probably a duplicate of #2309
Asyncio warning: socket.send() exception. I believe it is not aiohttp issue, eventually another frameworks suffer from the same infinite loop exception. after investigation:
finally work around try asyncio.shield() that let the task complete and serve another one 'Gracefully'
async def stream_vid(self, request):
response = web.StreamResponse()
response.content_type = "multipart/x-mixed-replace;boundary=frame"
await response.prepare(request)
try:
while self.sock_opened:
data = self.raw_frame
if not data:
break
await asyncio.shield(response.write(b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + data + b'\r\n\r\n'))
except BaseException as e:
print("asyncio socket.send() raised exception infinite no more %s" % e)
pass
finally:
print(response.status)
await response.write_eof()
works like a charm further readings https://gitlab.com/pgjones/quart/issues/240
I've stumbled on the same issue.
autoping=True, heartbeat=5
Setting the heartbeat on the server side to be safely longer than DOUBLE the time the client is starved (because aiohttp hardcodes self._pong_heartbeat = heartbeat / 2.0
) works around the problem.
In my application, I can reproduce the issue 100% of the times. I tried hard to replicate it in a POC, but failed - in the POC, the client is raising sane exceptions instead, either on send() (if the message is enough to saturate the output buffer) or on receive() (for small messages).
@initzx @asvetlov @crusaderky Is there a workaround for this issue ? I have faced with the same issue and due to silent behavior some data was not sent to server from my clients ...
I am interesting in workaround on client-side, because server could be stopped randomly by some reason ...
I wonder how we can use the try...except...
to catch this error, or else this will not recover by itself even if the network becomes stable.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
socket.send() raised exception.
...
...
app[worker.1]: [13-Jul-24 16:30:11 - WARNING] - asyncio - socket.send() raised exception.
Repo mein ye error ara he koi fixe karwa sakte hai..??
Looks like this is being worked on in cpython: https://github.com/python/cpython/pull/118960 So, hopefully will be resolved in an upcoming release.
Looks like this is being worked on in cpython: python/cpython#118960 So, hopefully will be resolved in an upcoming release.
That fix looks reasonable. We might be able to get rid of cleanup_closed
as well
Long story short
ws.send_json() fails with this warning:
WARNING -- asyncio.write : socket.send() raised exception.
ws is fromaiohttp.ClientSession().ws_connect()
Expected behaviour
An exception should have be raised along with a traceback message, but nothing happened.
Actual behaviour
It shows the warning and does nothing.
Steps to reproduce
You can see the code here As far as I know, there is no exact way of reproducing it. You just wait a bit for the bug to appear, likely due to some connection errors along the way?
Your environment
aiohttp 3.3.2
Ubuntu 16.04 LTS