Skip to content

Client gets disconnected due to race condition (enable_multithread) #210

@rabrahamkns

Description

@rabrahamkns

Hello
I found a race condition where a websocket server will disconnect a socketIO-client. This is happening because of a race condition between the ping loop thread and the data thread (where data is being sent). Here is how it goes:
If one thread starts sending a large frame, and it is broken into chunks, and then the second thread sends its data in the middle of the chunks, it breaks the socket io protocol. The header of each frame contains the length and some meta data, which match to a complete frame. But now the frame is polluted with data from 2 threads. As a result, the server drops the client’s connection since the header data is bad with "transport error" (“reserved fields must be empty”).
This is happening python2.7/dist-packages/websocket/_core.py line #276, send_frame method:

` def send_frame(self, frame):
"""
Send the data frame.

    frame: frame data created  by ABNF.create_frame

    >>> ws = create_connection("ws://echo.websocket.org/")
    >>> frame = ABNF.create_frame("Hello", ABNF.OPCODE_TEXT)
    >>> ws.send_frame(frame)
    >>> cont_frame = ABNF.create_frame("My name is ", ABNF.OPCODE_CONT, 0)
    >>> ws.send_frame(frame)
    >>> cont_frame = ABNF.create_frame("Foo Bar", ABNF.OPCODE_CONT, 1)
    >>> ws.send_frame(frame)

    """
    if self.get_mask_key:
        frame.get_mask_key = self.get_mask_key
    data = frame.format()
    length = len(data)
    trace("send: " + repr(data))

    with self.lock:
        while data:
            l = self._send(data)
            data = data[l:]

    return length

`

in socketIO-client lock is defined as NoLock, so it does nothing.
This is happening because enable_multithread in python2.7/dist-packages/websocket/_core.py inside craete_connection() is False by default, and I could not find a way to turn this on from socketIO-client.
To fix this I added this python2.7/dist-packages/socketIO_client/transports.py line #139:
kw['enable_multithread'] = True

And now the websocket send() method is guarded.
My server is websocket for node v4.5.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions