-
-
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
Network adapter going down does not disconnect the websockets #827
Comments
Thanks for report. |
The patch is welcome :) |
So I looked at it all this afternoon, but I'm not sure how to fix this bug.
This is where I'm stuck : I'm not sure what to do now. The asyncio documentation describes that
So I'm not sure why it is never called. Any help would be greatly appreciated ! |
If connection_lost is not being called aiohttp can not do anything. But that might be buggy device driver |
also you can put some print statements into asyncio event loop and see if asyncio received info from kernel for specific socket. |
Thanks for the info. I'm just wondering, can you reproduce the error I described in the first post of this issue ? Just to check if it's a bug happening on some platforms only. Where should I put trace logging in asyncio loop ? |
After reading this : http://superuser.com/questions/1021988/connection-remains-flagged-as-established-even-if-host-is-unconnected |
Ok I found a way to detect disconnections by using a heartbeat mecanism : async def heartbeat(ws):
"""
:param asyncio.WebsocketClientResponse ws: the ws to do heartbeat with
:return:
"""
future_pong = None
def pong_callback():
if future_pong:
future_pong.set_result(True)
async def ping_loop():
nonlocal future_pong
future_pong = asyncio.Future()
missed_heartbeats = 0
while not ws.closed:
await asyncio.sleep(15)
if not ws.closed:
try:
future_pong = asyncio.Future()
ws.ping()
await asyncio.wait_for(future_pong, 15)
missed_heartbeats = 0
except asyncio.TimeoutError:
missed_heartbeats += 1
finally:
if missed_heartbeats > 3:
await ws.close()
asyncio.ensure_future(ping_loop())
return pong_callback I use it this way : import aiohttp
import asyncio
async def connect():
try:
async with aiohttp.ws_connect('ws://metab.ucoin.io:9201/ws/block') as the_ws:
heartbeat_cb = heartbeat(the_ws)
async for msg in the_ws:
if msg.tp == aiohttp.MsgType.text:
print(msg.data)
elif msg.tp == aiohttp.MsgType.closed:
print("Closed")
break
elif msg.tp == aiohttp.MsgType.error:
print("Error")
break
elif msg.tp == aiohttp.MsgType.pong:
heartbeat_cb()
except Exception as e:
print(str(e))
finally:
print("Disconnected")
loop = asyncio.get_event_loop()
loop.run_until_complete(connect())
print("Finished") I suppose it could be used for the following issue : #777 What do you think ? |
Heartbeat should be implemented by aiohttp. |
added |
Long story short
I'm working on a software which uses aiohttp websockets to connect to multiple network nodes. There is a bug with aiohttp and its websockets. When the users are disconnecting from wifi, or set their computers on standby and waking their computers later on, the software does not detect the disconnection.
Expected behaviour
When the network adapter is disconnected, the websockets should raise an exception and close themselves.
Actual behaviour
The websockets do not close.
Steps to reproduce
1- When connected to the internet, run the following code :
2- It will print json data from an ucoin blockchain. Disconnect your internet
3- It never prints the exception, neither "Disconnected" nor "Finished" messages.
Your environment
I'm using python3 with archlinux 64 bits.
The text was updated successfully, but these errors were encountered: