Description
Hello, this is the same issue with #24842. Open another one since I can not reopen it because this issue has not been fixed eventually. It still happens occasionally when using org.springframework.web.socket.adapter.standard.StandardWebSocketSession
.
The native org.apache.tomcat.websocket.wsSession
will set its state finally to CLOSED
after calling fireEndpointOnClose
when calling StandardWebSocketSession#closeInternal. (tomcat-embed-websocket:10.1.39)
public class WsSession implements Session {
...
public void doClose(CloseReason closeReasonMessage, CloseReason closeReasonLocal, boolean closeSocket) {
if (!state.compareAndSet(State.OPEN, State.OUTPUT_CLOSING)) {
return;
}
...
fireEndpointOnClose(closeReasonLocal);
if (!state.compareAndSet(State.OUTPUT_CLOSING, State.OUTPUT_CLOSED) || closeSocket) {
state.set(State.CLOSED);
closeConnection();
} else {
sessionCloseTimeoutExpiry =
Long.valueOf(System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(getSessionCloseTimeout()));
}
...
}
...
}
The method fireEndpoinOnClose
will call the expression this.handler.afterConnectionClosed in org.springframework.web.socket.adapter.standar.StandardWebSocketHandlerAdapter#onClose
.
Finally in org.springframework.web.socket.messaging.StompSubProtocolHandler#afterSessionEnded
the decoder of the session will be removed.
However, during above process, the state of the session is still OUTPUT_ClOSING
which is marked as true
for isOpen
method as below.
public class WsSession implements Session {
...
@Override
public boolean isOpen() {
return state.get() == State.OPEN || state.get() == State.OUTPUT_CLOSING || state.get() == State.CLOSING;
}
...
}
Therefore, with the fix in previous issue, when the decoder is null for the session, the session might still be in state of OUTPUT_CLOSING
.
BTW. This does not happen when using SocketJsSession, because the state will be set to CLOSED
, here, before calling afterConnectionClosed