This PR fixes an issue where blocking ws.receive() calls are not informed of the connection closing when a Ping/Pong related timeout occurs.
Reproducing:
server.py
from flask import Flask, request
from simple_websocket import Server, ConnectionClosed
app = Flask(__name__)
@app.route('/command', websocket=True)
def command():
ws = Server.accept(request.environ, ping_interval=25)
try:
while True:
# blocking receive() call
# pings used to detect disconnections
data = ws.receive()
# .. do stuff with data ..
except ConnectionClosed:
print("Connection closed, cleaning up..", flush=True)
# .. other cleanup ..
return ''
if __name__ == '__main__':
app.run()
client.py
from simple_websocket import Client, ConnectionClosed
def main():
ws = Client.connect('ws://localhost:5000/command')
try:
while True:
data = input('> ')
ws.send(data)
data = ws.receive()
print(f'< {data}')
except (KeyboardInterrupt, EOFError, ConnectionClosed):
ws.close()
if __name__ == '__main__':
main()
Run server.py, run client.py, and Ctrl-C the client. Observe that ConnectionClosed is properly thrown
Run client.py again and Ctrl-Z to simulate a connection dropout. Wait until the Ping/Pong timeout occurs: sleep 50
Restore the client. The connection was already dropped and the simple-websocket server thread was already closed, but blocking readers on the server are not informed of the condition, causing them to be stuck forever.
Hi!
This PR fixes an issue where blocking
ws.receive()
calls are not informed of the connection closing when a Ping/Pong related timeout occurs.Reproducing:
server.py
client.py
server.py
, runclient.py
, and Ctrl-C the client. Observe thatConnectionClosed
is properly thrownclient.py
again and Ctrl-Z to simulate a connection dropout. Wait until the Ping/Pong timeout occurs:sleep 50