-
-
Notifications
You must be signed in to change notification settings - Fork 150
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
Socketio client isn't notified of disconnect due to _reset() call in client.py #254
Comments
This is in part related to miguelgrinberg/python-socketio#485. The part that is new is the fact that the disconnect handler is not being invoked when the server returns an error. That is an omission. The part that this issue has in common with the other one is the lack of reconnect attempts when the server returns an error response. I have to think about how to handle this, because a 400 error as you suggest as an example is unlikely to succeed on a retry. 5xx errors make sense to retry though. Your suggestion of just skipping the reset is incorrect, I believe. All that does is ignore the request that ended in error and keep going, without disconnecting. The correct behavior is to disconnect and then reconnect. If you don't disconnect, then some events that were exchanged in the request that ended up in error will be silently discarded. |
Yep, I saw miguelgrinberg/python-socketio#485 and thought it might be related. The solution you gave there didn't work in my case though (since the socketio client never even realized it was disconnected, even though the engineio client was disconnected)--so I figured it made sense to post a separate bug. As for 400 errors, it looks like the server generates them in a wide variety of circumstances including when a session ID is invalid. It seems like that's at least one situation where a retry is likely to succeed, because it doesn't mean there's any underlying problem--just that the server forgot about the client somehow. (And in my case an attempt to retry does indeed succeed, because the client tries to use a new SID on reconnect.) As for skipping the reset, I tried removing it and everything reconnected as expected:
So when you omit the |
Hmm. Okay, I'll test removing the resets. I didn't think it would do what you describe, but I'll figure it out. Thanks. |
Your solution does not work, as I expected. When a request comes back with a non 2xx status code, the read and write loop tasks must exit. Calling So I disagree that the |
Yep, you're right--apologies for not catching that myself. I've edited the title of the bug to reflect that the calls to Given that, I can think of two possible solutions and I'm not sure which is better:
And then, replace
There are probably other solutions--WDYT? |
I'm running a python-socketio server in the cloud using Google App Engine, but whenever I restart my instance, my python-socketio client never realizes that it's been disconnected even though it receives a 400 error from the server. Instead, the python-socketio client just sits there (or exits if it's currently blocking on a call to
wait()
).The expected behavior is that if reconnection is set to true, the client should detect a 400 error and attempt to reconnect.
I've tracked down the bug to line 694 in client.py in the engine.io library--specifically the call to
self._reset()
when the server returns an HTTP error code. Here's how it works:_write_loop()
when using polling mode, and then calls_reset()
on line 694._reset()
, the engineio client attributestate
is set to"disconnected"
_write_loop()
breaks, and shortly thereafter, the_read_loop()
also gets a 400 error and breaks._reset()
already set thestate
to disconnected, the_read_loop()
code starting at line 597 to call the"disconnect"
callback is never run before the_read_loop()
function returns"disconnect"
callback is never run,_handle_eio_disconnect()
in socketio client.py is never called, so the reconnection logic never gets triggered.Below are the smallest examples of a client and server I could write that reproduce the error:
client.py:
server.py:
And the logs:
client.py:
server.py
The solution seems pretty straightforward: remove the call to
_reset()
on line 694 of client.py.Also, I haven't tested to see if the same bug happens with an asynioc_client.py, but it looks like it has the same weird call to
_reset()
, so it probably does.If you'd like, I'd be happy to submit a PR removing those spurious calls to
_reset()
.Thanks so much!
The text was updated successfully, but these errors were encountered: