-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebSocket silently blocks handler indefinitely #4877
Comments
I believe this is a known issue, and the API will probably be changed in 4.0 to raise an exception during sending. See #3391 (comment). I'd suggest enabling heartbeats in your Then you can terminate your loop. I don't remember off-hand if the heartbeat failure raises an exception from the receive, or if you need to then check |
I think the situation is a bit worse than with #3391. I have tried both heartbeats and testing for ws.closed before each ws command, but the handler ends up blocked still. I can see that the handler is stalled on DataQueue.read() where it is waiting for it's self._waiter future to end. However, the result of this future is never set (even when the socket connection is detected as being lost). I'm guessing the connection_lost() callback should propagate an exception to the _waiter somehow. |
workaround: I plan on using receive_timeout to eventually be notified of dead connection. Initially I didn't think receive timeout was raising an exception, but it looks like it does. |
I wasn't able to reproduce the blocking handler behavior with the following test on 32833c3: async def test_ws_not_blocks_on_disconnect(aiohttp_client) -> None:
handler_finished = asyncio.Future()
async def handler(request):
try:
ws = web.WebSocketResponse()
await ws.prepare(request)
for i in range(10):
data = await ws.receive_str()
await ws.send_str(data)
return ws
finally:
handler_finished.set_result(None)
app = web.Application()
app.router.add_route("GET", "/", handler)
client = await aiohttp_client(app)
with pytest.raises(KeyboardInterrupt):
async with client.ws_connect("/") as ws:
for i in range(5):
await ws.send_str(f"stuff {i}")
print(await ws.receive_str())
raise KeyboardInterrupt()
assert handler_finished.done() In the issue description the code should hit the line |
Based on the above comments, I'll close this in favour of the linked issue. |
🐞 Describe the bug
I have a simple client/server using aiohttp WebSockets. If the client disconnects unexpectedly (link down, ctrl+C, etc), then the server WebSocket handler blocks indefinitely.
💡 To Reproduce
Server:
Client:
End the client early with ctrl+C. The server blocks waiting for the client.
💡 Expected behavior
I would expect an exception to be raised on the server as it waits for client data. Investigation shows that
BaseProtocol.connection_lost() callback is run, but does not result in an exception being raised.
📋 Your version of the Python
Python 3.7.7
aiohttp 3.6.2
📋 Your version of the aiohttp/yarl/multidict distributions
📋 Additional context
Fedora 31
possibly related bug: #3122
The text was updated successfully, but these errors were encountered: