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
IMPORTANT: If you have a question, or you are not sure if you have found a bug in this package, then you are in the wrong place. Hit back in your web browser, and then open a GitHub Discussion instead. Likewise, if you are unable to provide the information requested below, open a discussion to troubleshoot your issue.
Describe the bug
A WebSocket PONG miss while using uWSGI will leave an open TCP connection on python-engineio, gradually consuming more CPU.
To Reproduce
Run a python-engineio based websocket server, e.g. using Flask-SocketIO
Connect to the server with any websocket client.
On the client side, intentionally miss a WebSocket PONG.
uWSGI will complain that the pong has been missed, emitting a log (uWSGI code), resulting uwsgi_websocket_recv() to return an empty buffer.
Upon the empty buffer, uWSGI's Python binding will raise an IOError during uwsgi.websocket_recv() (uWSGI code).
python-engineio's uWSGIWebSocket.wait() catches the IOError and returns None (python-engineio code).
python-engineio's Socket._websocket_handler() will receive the returned None, break out of the main loop (python-engineio code), join the writer_task(), and call Socket.close().
Socket.close() will attempt to send the CLOSE packet, but since writer_task() is already joined, the packet will only be queued, never sent.
Since uwsgi_disconnect() is never called in this flow, uWSGI's socket is never explicitly closed, hence leaked.
Expected behavior
The connection should be explicitly closed.
Additional context
Seems like #237 was about this. I'll see if I can come up with a patch, but I'll need some help for it not to affect other websocket drivers.
The text was updated successfully, but these errors were encountered:
Forgot the most important part: huge thank-you for your work!
As for the patch, I've added self.close() to all IOError catches in uWSGIWebSocket. So far it looks like the connections are now getting freed alright.
One more: it turns out that uWSGI can also raise IOError during send(). self._send(msg) within uWSGIWebSocket.wait() must also catch it for another self.close(). Otherwise, it can leave the file descriptor to the TCP port unbound, which seems to make select() for read always return immediately, and cause select_greenlet_runner() to go in an infinite loop, eating up CPU cycles.
And also, the close() method can be reordered by putting uwsgi disconnect to the back, to prevent select_greenlet_runner() raising OSError. Harmless error, but still.
IMPORTANT: If you have a question, or you are not sure if you have found a bug in this package, then you are in the wrong place. Hit back in your web browser, and then open a GitHub Discussion instead. Likewise, if you are unable to provide the information requested below, open a discussion to troubleshoot your issue.
Describe the bug
A WebSocket PONG miss while using uWSGI will leave an open TCP connection on python-engineio, gradually consuming more CPU.
To Reproduce
uwsgi_websocket_recv()
to return an empty buffer.uwsgi.websocket_recv()
(uWSGI code).uWSGIWebSocket.wait()
catches the IOError and returns None (python-engineio code).Socket._websocket_handler()
will receive the returned None, break out of the main loop (python-engineio code), join thewriter_task()
, and callSocket.close()
.Socket.close()
will attempt to send the CLOSE packet, but sincewriter_task()
is already joined, the packet will only be queued, never sent.uwsgi_disconnect()
is never called in this flow, uWSGI's socket is never explicitly closed, hence leaked.Expected behavior
The connection should be explicitly closed.
Additional context
Seems like #237 was about this. I'll see if I can come up with a patch, but I'll need some help for it not to affect other websocket drivers.
The text was updated successfully, but these errors were encountered: