Synchronize everything going on the event queue. Resolves #98 and #54 #102
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
So:
While an event queue (used for connecting, disconnecting, listener events) is shutting down, it still continues as it finishes its final tasks. While it is doing so, if a function that requires an event queue executes, it creates a new one.
This situation can lead to two event queues running at the same time. Issues #98 and #54 were, I believe, caused by an extremely subtle race condition where certain factors (e.g. custom reconnection logic, multiple instances of Pusher etc.) would cause multiple connection operations to be called at the same time. If a socket has been shut down - leading to an event queue being asked to shut down - and then there are multiple calls to connect executed on more than one event queue, you could get a race condition.
This led to inconsistencies regarding the connection
state. If two threads see that that thestateisDISCONNECTED, one gets there first and updates the state toCONNECTINGand then the second thread tries to update the state toCONNECTING, we will getjava.lang.IllegalArgumentException: Attempted to create an connection state update where both previous and current state are: CONNECTING.In light of this, all Runnables put on the event queue are now wrapped in a synchronized block. The factory forever holds this lock and in the event there are two concurrent event queues, it will synchronize the Runnables.
cc @mdpye