You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
python -m websockets blocks until open_timeout when connection fails #1592
$ python -m websockets wss://.../
^C
Traceback (most recent call last):
File "/Users/myk/dev/websockets/src/websockets/sync/client.py", line 378, in connect
connection.handshake(
~~~~~~~~~~~~~~~~~~~~^
additional_headers,
^^^^^^^^^^^^^^^^^^^
user_agent_header,
^^^^^^^^^^^^^^^^^^
deadline.timeout(),
^^^^^^^^^^^^^^^^^^^
)
^
File "/Users/myk/dev/websockets/src/websockets/sync/client.py", line 101, in handshake
raise self.protocol.handshake_exc
File "/Users/myk/dev/websockets/src/websockets/client.py", line 325, in parse
self.process_response(response)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/Users/myk/dev/websockets/src/websockets/client.py", line 142, in process_response
raise InvalidStatus(response)
websockets.exceptions.InvalidStatus: server rejected WebSocket connection: HTTP 302
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/Users/myk/dev/websockets/src/websockets/__main__.py", line 159, in <module>
main()
~~~~^^
File "/Users/myk/dev/websockets/src/websockets/__main__.py", line 131, in main
websocket = connect(args.uri)
File "/Users/myk/dev/websockets/src/websockets/sync/client.py", line 385, in connect
connection.recv_events_thread.join()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/Users/myk/.pyenv/versions/3.13.1/lib/python3.13/threading.py", line 1092, in join
self._handle.join(timeout)
~~~~~~~~~~~~~~~~~^^^^^^^^^
KeyboardInterrupt
Connecting to the same server directly with websockets.sync.client.connect doesn't block.
closing the socket doesn't interrupt recv() because recv() isn't running in the main thread — and interruption is based on signals which are only received by the main thread.
This is an unexpected side effect of migrating python -m websockets from the asyncio to the sync implementation.
The main constraint of python -m websockets is that both reading from stdin and from the WebSocket connection must be interruptible. Since input() and the sync implementation (in its current version) are only interruptible by signals, both would need to run in the main thread, which would require running two processes.
The most elegant option could be to go back to an asyncio implementation and do non-blocking read of sys.stdin. This blog post suggests that it's doable — solution at the bottom.
Outside of python -m websockets, the problem could still happen for a any connection running in a non-main thread, including all server connections. This requires investigation.
Activity
aaugustin commentedon Feb 10, 2025
Actually this is a race condition.
When this line:
websockets/src/websockets/sync/connection.py
Line 814 in 8c9f6fc
runs before this line:
websockets/src/websockets/sync/client.py
Line 384 in 8c9f6fc
closing the socket doesn't interrupt
recv()becauserecv()isn't running in the main thread — and interruption is based on signals which are only received by the main thread.This is an unexpected side effect of migrating
python -m websocketsfrom the asyncio to the sync implementation.aaugustin commentedon Feb 10, 2025
The main constraint of
python -m websocketsis that both reading from stdin and from the WebSocket connection must be interruptible. Sinceinput()and the sync implementation (in its current version) are only interruptible by signals, both would need to run in the main thread, which would require running two processes.The most elegant option could be to go back to an asyncio implementation and do non-blocking read of sys.stdin. This blog post suggests that it's doable — solution at the bottom.
aaugustin commentedon Feb 10, 2025
Outside of
python -m websockets, the problem could still happen for a any connection running in a non-main thread, including all server connections. This requires investigation.Rewrite interactive client (again) without threads.