[Java] Catch exceptions from users and change close state correctly (#29249)

* [Java] Catch exceptions from users and change close state correctly

* log

* link
This commit is contained in:
Brennan 2021-01-15 11:21:48 -08:00 committed by GitHub
parent fe37d39281
commit 264e185bdc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 10 deletions

View File

@ -517,25 +517,32 @@ public class HubConnection implements AutoCloseable {
RuntimeException exception = null; RuntimeException exception = null;
this.state.lock(); this.state.lock();
try { try {
ConnectionState connectionState = this.state.getConnectionStateUnsynchronized(true);
if (connectionState == null)
{
this.logger.error("'stopConnection' called with a null ConnectionState. This is not expected, please file a bug. https://github.com/dotnet/aspnetcore/issues/new?assignees=&labels=&template=bug_report.md");
return;
}
// errorMessage gets passed in from the transport. An already existing stopError value // errorMessage gets passed in from the transport. An already existing stopError value
// should take precedence. // should take precedence.
if (this.state.getConnectionStateUnsynchronized(false).stopError != null) { if (connectionState.stopError != null) {
errorMessage = this.state.getConnectionStateUnsynchronized(false).stopError; errorMessage = connectionState.stopError;
} }
if (errorMessage != null) { if (errorMessage != null) {
exception = new RuntimeException(errorMessage); exception = new RuntimeException(errorMessage);
logger.error("HubConnection disconnected with an error {}.", errorMessage); logger.error("HubConnection disconnected with an error {}.", errorMessage);
} }
ConnectionState connectionState = this.state.getConnectionStateUnsynchronized(true); this.state.setConnectionState(null);
if (connectionState != null) { connectionState.cancelOutstandingInvocations(exception);
connectionState.cancelOutstandingInvocations(exception); connectionState.close();
connectionState.close();
this.state.setConnectionState(null);
}
logger.info("HubConnection stopped."); logger.info("HubConnection stopped.");
this.state.changeState(HubConnectionState.CONNECTED, HubConnectionState.DISCONNECTED); // We can be in the CONNECTING or CONNECTED state here, depending on if the handshake response was received or not.
// connectionState.close() above will exit the Start call with an error if it's still running
this.state.changeState(HubConnectionState.DISCONNECTED);
} finally { } finally {
this.state.unlock(); this.state.unlock();
} }
@ -543,7 +550,11 @@ public class HubConnection implements AutoCloseable {
// Do not run these callbacks inside the hubConnectionStateLock // Do not run these callbacks inside the hubConnectionStateLock
if (onClosedCallbackList != null) { if (onClosedCallbackList != null) {
for (OnClosedCallback callback : onClosedCallbackList) { for (OnClosedCallback callback : onClosedCallbackList) {
callback.invoke(exception); try {
callback.invoke(exception);
} catch (Exception ex) {
logger.warn("Invoking 'onClosed' method failed:", ex);
}
} }
} }
} }
@ -1519,6 +1530,16 @@ public class HubConnection implements AutoCloseable {
} }
} }
public void changeState(HubConnectionState to) {
this.lock.lock();
try {
logger.debug("The HubConnection is transitioning from the {} state to the {} state.", this.hubConnectionState, to);
this.hubConnectionState = to;
} finally {
this.lock.unlock();
}
}
public void lock() { public void lock() {
this.lock.lock(); this.lock.lock();
} }

View File

@ -125,6 +125,9 @@ class OkHttpWebSocketWrapper extends WebSocketWrapper {
stateLock.unlock(); stateLock.unlock();
} }
checkStartFailure(null); checkStartFailure(null);
// Send the close frame response if this was a server initiated close, otherwise noops
webSocket.close(1000, "");
} }
@Override @Override