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

[Java] Don't call onClose when WebSocket connection is not open #28004

Merged
merged 3 commits into from
Nov 23, 2020

Conversation

BrennanConroy
Copy link
Member

Fixes #27438

Description

If an endpoint doesn't support WebSockets or some kind of connection issue occurs then the WebSockets onFailure method will be called which will call onClose. The onClose callback is only expected to be called when a connection is already connected and will fail when in this state, this results in hubConnection.start() never completing or in some environments, the client crashes due to an unhandled exception.

Customer Impact

Bug reported in #27438 as well as an internal partner.
The bug will cause hubConnection.start() to not finish or client crashes.
A workaround is to only use LongPolling for the client, WebSockets is the best transport so this isn't a great workaround.

Regression?

Yes, regressed from 3.1 to 5.0

Risk

Low.
Issue is easy to repro and we have prior art with a similar change #14114

@BrennanConroy BrennanConroy added Servicing-consider Shiproom approval is required for the issue area-signalr Includes: SignalR clients and servers feature-client-java Related to the SignalR Java client labels Nov 19, 2020
@BrennanConroy BrennanConroy added this to the 5.0.1 milestone Nov 19, 2020
@ghost
Copy link

ghost commented Nov 19, 2020

Hello human! Please make sure you've included the Shiproom Template in a comment or (preferably) the PR description. Also, make sure this PR is not marked as a draft and is ready-to-merge.

}
checkStartFailure();
checkStartFailure(null);
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ever possible for both onClosing and onFailure to be called on the same WebSocketListener?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe so

@@ -30,7 +30,7 @@
private WebSocketOnClosedCallback onClose;
private CompletableSubject startSubject = CompletableSubject.create();
private CompletableSubject closeSubject = CompletableSubject.create();
private final ReentrantLock closeLock = new ReentrantLock();
private final ReentrantLock stateLock = new ReentrantLock();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little unrelated to this pr, but do you know why we use ReentrantLock instead of synchronized?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure there is a good reason. Maybe just oversight

…oft/signalr/OkHttpWebSocketWrapper.java

Co-authored-by: Stephen Halter <halter73@gmail.com>
@BrennanConroy
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

}
// Only call onClose if connection is open
if (isOpen) {
onClose.invoke(code, reason);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we sometimes discard the onClosing code/reason, we should log it.

}
checkStartFailure();
checkStartFailure(null);
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
logger.error("WebSocket closed from an error: {}.", t.getMessage());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And while I'm thinking about logging. I assume the following will produce more helpful output.

Suggested change
logger.error("WebSocket closed from an error: {}.", t.getMessage());
logger.error("WebSocket closed from an error.", t);

@BrennanConroy BrennanConroy added Servicing-approved Shiproom has approved the issue and removed Servicing-consider Shiproom approval is required for the issue labels Nov 21, 2020
@BrennanConroy
Copy link
Member Author

Servicing approved over email.

Still need to react to final feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-signalr Includes: SignalR clients and servers feature-client-java Related to the SignalR Java client Servicing-approved Shiproom has approved the issue
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants