feus4177 / socketIO-client-2

A socket.io client library for Python
http://pypi.python.org/pypi/socketIO-client-2
MIT License
16 stars 15 forks source link

ssl connection race with flask socket.io server app #14

Open tuxembedded opened 6 years ago

tuxembedded commented 6 years ago

When I use the current version it seems that there is a race when the connection starts. After ssl connection is established, heartbeat-packet is sent through websocket transport in a thread in parallel to the "test" namespace-join-packet. The issue only seems to happen if client and server run on different machines, connected by the Internet. Running server and client on the same machine seems to work.

Recent repo code fires ConnectionError-exception and prints it in heartbeats.py:37

        except ConnectionError:
            logging.debug('[heartbeat connection error]')

This exception happens there in detail:

2018-01-10 18:46:08,905 - DEBUG - abc.com:5001/socket.io [heartbeat reset]
2018-01-10 18:46:08,906 - ERROR - send disconnected ([SSL: BAD_WRITE_RETRY] bad write retry (_ssl.c:2074))
Traceback (most recent call last):
  File "/home/daniel/devel/abc/python/modules/socketIO_client/transports.py", line 177, in send_packet
    self._connection.send(packet)
  File "/usr/lib/python3.6/site-packages/websocket/_core.py", line 234, in send
    return self.send_frame(frame)
  File "/usr/lib/python3.6/site-packages/websocket/_core.py", line 259, in send_frame
    l = self._send(data)
  File "/usr/lib/python3.6/site-packages/websocket/_core.py", line 423, in _send
    return send(self.sock, data)
  File "/usr/lib/python3.6/site-packages/websocket/_socket.py", line 116, in send
    return sock.send(data)
  File "/usr/lib/python3.6/ssl.py", line 941, in send
    return self._sslobj.write(data)
  File "/usr/lib/python3.6/ssl.py", line 642, in write
    return self._sslobj.write(data)
ssl.SSLError: [SSL: BAD_WRITE_RETRY] bad write retry (_ssl.c:2074)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/daniel/devel/abc/python/modules/socketIO_client/heartbeats.py", line 29, in run
    self._send_heartbeat()
  File "/home/daniel/devel/abc/python/modules/socketIO_client/__init__.py", line 203, in _ping
    engineIO_packet_type, engineIO_packet_data)
  File "/home/daniel/devel/abc/python/modules/socketIO_client/transports.py", line 181, in send_packet
    raise ConnectionError('send disconnected (%s)' % e)
socketIO_client.exceptions.ConnectionError: send disconnected ([SSL: BAD_WRITE_RETRY] bad write retry (_ssl.c:2074))
2018-01-10 18:46:08,906 - DEBUG - abc.com:5001/socket.io [socket.io packet sent] 0/test,
2018-01-10 18:46:08,908 - DEBUG - [heartbeat connection error]

It happens roughly 50% of connection attempts.

The XHR_PollingTransport has a threading.Lock for send_packet. Why isn't there one for the WebsocketTransport? The issue seems to be fixed if I use the lock in XHR_PollingTransport also for WebsocketTransport, see attached patch: transports-patch.txt