Skip to content
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

Back-to-back event receiving with gevent #47

Open
rayalan opened this issue Feb 19, 2016 · 4 comments
Open

Back-to-back event receiving with gevent #47

rayalan opened this issue Feb 19, 2016 · 4 comments

Comments

@rayalan
Copy link

rayalan commented Feb 19, 2016

I'm seeing a problem with receiving multiple events in v0.5.2. I have a browser that sends multiple events. However, flask-uwsgi-websocket only reads 1 event every timeout seconds (30, in my case). I believe the problem is two-fold:

  1. _gevent.py, line 70: The max receive queue size shouldn't be limited to 1.
  2. The clause around recv_is_set() should make sure that it reads all the events, with a minimum of one event. This seems to work for me:
elif recv_event.is_set():
    try:
        incoming_event = None
        is_first = True
        while incoming_event or is_first:
            incoming_event = uwsgi.websocket_recv_nb()
            if is_first or incoming_event:
                recv_queue.put(incoming_event)
            is_first = False
        recv_event.clear()
        listening = spawn(listener, client)
    except IOError:
        client.connected = False

The above can be cleaned up quite a bit. I also suspect that it is safe to reset the clear() flag before we finish reading all the current events. However, I rearranged it for testing purposes and I haven't gone back and verified that theory.

@rayalan
Copy link
Author

rayalan commented Feb 20, 2016

I dug into this a bit more. There seem to be a couple issues doing on here:

  1. Suppose that client.fd receives 200 bytes. As long as no bytes have been read, select(client.fd, [], timeout) returns instantly. As soon as a byte has been read, select(client.fd, [], timeout) takes timeout to return -- regardless of whether 1 or 200 bytes have been read.
  2. Some browsers seem to send back-to-back empty messages, which all need to get read from the system. If empty messages are left unread, they seem to prevent PONG messages from being sent (I'm not sure in which direction), which causes the socket to timeout. I ended up with this implementation:
            elif recv_event.is_set():
                recv_event.clear()
                try:
                    message = True
                    while message:
                        message = uwsgi.websocket_recv_nb()
                        recv_queue.put(message)
                    listening = spawn(listener, client)
                except IOError:
                    client.connected = False

It ends up writing an empty message for every event, but better than the alternatives.

@zeekay
Copy link
Owner

zeekay commented Feb 20, 2016

That seems like a nice solution, would you like to send a PR?

@rayalan
Copy link
Author

rayalan commented Feb 24, 2016

I will; it may be a couple days.

@rayalan
Copy link
Author

rayalan commented Feb 26, 2016

Created #48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants