vs-streamjsonrpc
vs-streamjsonrpc copied to clipboard
WebSocket gracefull shutdown exception
Hi, I have regular .net clients and aspNetCore server. When client closes I call webSocket.CloseOutputAsync. This works, I get no exceptions on client or server.
But when trying to do the same on server, it always generate exception, and I tried both webSocket.CloseAsync or webSocket.CloseOutputAsync. With webSocket.CloseOutputAsync I get an exeption on server happens here in WebSocketMessageHandler.cs:
if (result.MessageType == WebSocketMessageType.Close)
{
await this.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed as requested.", CancellationToken.None).ConfigureAwait(false);
return null;
}
Exception thrown: 'System.Net.WebSockets.WebSocketException' in System.Private.CoreLib.dll The WebSocket is in an invalid state ('Closed') for this operation. Valid states are: 'Open, CloseReceived, CloseSent'
I changed the code to this and it seems to fix the exception, but not sure if its the correct fix:
if (result.MessageType == WebSocketMessageType.Close)
{
if (this.WebSocket.State == WebSocketState.CloseReceived)
await this.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed as requested.", CancellationToken.None).ConfigureAwait(false);
return null;
}
Or maybe just check for all the valid states 'Open, CloseReceived, CloseSent'
I'm afraid web socket termination is an area I'm not too familiar with either. We occasionally have unit test failures in this area. If you or anyone else learns of a fix to this library for it, I'd love to hear it.
I can only suggest to prevent the exception by calling CloseAsync only for the allowed states as presented by exception. It might not really fix anything, but it does not crash anymore:-)
if (result.MessageType == WebSocketMessageType.Close)
{
if (this.WebSocket.State == WebSocketState.Open
|| this.WebSocket.State == WebSocketState.CloseReceived
|| this.WebSocket.State == WebSocketState.CloseSent)
await this.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed as requested.", CancellationToken.None).ConfigureAwait(false);
return null;
}