WebSocketServerSockJsSession uses dedicated disconnect lock

Issue: SPR-14917
(cherry picked from commit a49809b)
This commit is contained in:
Juergen Hoeller
2016-11-21 17:24:44 +01:00
parent 872d6ef55a
commit ac30bcb0eb

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -42,6 +42,7 @@ import org.springframework.web.socket.sockjs.transport.SockJsServiceConfig;
* A SockJS session for use with the WebSocket transport. * A SockJS session for use with the WebSocket transport.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 4.0 * @since 4.0
*/ */
public class WebSocketServerSockJsSession extends AbstractSockJsSession implements NativeWebSocketSession { public class WebSocketServerSockJsSession extends AbstractSockJsSession implements NativeWebSocketSession {
@@ -54,6 +55,8 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
private final Object initSessionLock = new Object(); private final Object initSessionLock = new Object();
private final Object disconnectLock = new Object();
private volatile boolean disconnected; private volatile boolean disconnected;
@@ -136,18 +139,14 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
@Override @Override
public Object getNativeSession() { public Object getNativeSession() {
if ((this.webSocketSession != null) && (this.webSocketSession instanceof NativeWebSocketSession)) { return (this.webSocketSession instanceof NativeWebSocketSession ?
return ((NativeWebSocketSession) this.webSocketSession).getNativeSession(); ((NativeWebSocketSession) this.webSocketSession).getNativeSession() : null);
}
return null;
} }
@Override @Override
public <T> T getNativeSession(Class<T> requiredType) { public <T> T getNativeSession(Class<T> requiredType) {
if ((this.webSocketSession != null) && (this.webSocketSession instanceof NativeWebSocketSession)) { return (this.webSocketSession instanceof NativeWebSocketSession ?
return ((NativeWebSocketSession) this.webSocketSession).getNativeSession(requiredType); ((NativeWebSocketSession) this.webSocketSession).getNativeSession(requiredType) : null);
}
return null;
} }
@@ -166,7 +165,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
scheduleHeartbeat(); scheduleHeartbeat();
this.openFrameSent = true; this.openFrameSent = true;
} }
catch (Exception ex) { catch (Throwable ex) {
tryCloseWithSockJsTransportError(ex, CloseStatus.SERVER_ERROR); tryCloseWithSockJsTransportError(ex, CloseStatus.SERVER_ERROR);
} }
} }
@@ -196,10 +195,8 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
@Override @Override
public void sendMessageInternal(String message) throws SockJsTransportFailureException { public void sendMessageInternal(String message) throws SockJsTransportFailureException {
// Open frame not sent yet? // Open frame not sent yet?
// If in the session initialization thread, then cache, otherwise wait. // If in the session initialization thread, then cache, otherwise wait.
if (!this.openFrameSent) { if (!this.openFrameSent) {
synchronized (this.initSessionLock) { synchronized (this.initSessionLock) {
if (!this.openFrameSent) { if (!this.openFrameSent) {
@@ -208,6 +205,7 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
} }
} }
} }
cancelHeartbeat(); cancelHeartbeat();
writeFrame(SockJsFrame.messageFrame(getMessageCodec(), message)); writeFrame(SockJsFrame.messageFrame(getMessageCodec(), message));
scheduleHeartbeat(); scheduleHeartbeat();
@@ -224,10 +222,12 @@ public class WebSocketServerSockJsSession extends AbstractSockJsSession implemen
@Override @Override
protected void disconnect(CloseStatus status) throws IOException { protected void disconnect(CloseStatus status) throws IOException {
synchronized (this) { if (isActive()) {
if (isActive()) { synchronized (this.disconnectLock) {
this.disconnected = true; if (isActive()) {
this.webSocketSession.close(status); this.disconnected = true;
this.webSocketSession.close(status);
}
} }
} }
} }