High CPU spike on client workstation when the websocket is disconnected due to server unavailability

Open
#658 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
csharp
Domain
networking

Research direction

Start by tracing WebSocketSharp.Ext.ReadBytesAsync from the reported SslStream.BeginRead stack frame, then inspect how an aborted connection is handled. Reproduce a server-unavailability disconnect and profile the client during the reported 15-second CPU spike. Done means the failure no longer causes sustained excessive CPU use and the relevant regression behavior is covered by an available test.

Written by the indexing model from the issue text.

Description

Problem: We use Web-Socket sharp from a desktop application which is written in c#. This desktop application runs of hundreds of client workstations. We have noticed high CPU spike on client workstations for 15 seconds after the web-socket is abruptly closed due to server unavailability (e.g. service restart). This high CPU spike is observed at the same time on all the VDI where our application had opened a web-socket, hence the spike occurring for small duration causes the entire VDI server to run out of resources (as the spike gets multiplied by number of users having the CPU spike at the same time).

Observations: The method SslStream.BeginRead causes high CPU usage as captured by the profiler and also the following error in printed in logs. We have tried adding some checks before calling the SslStream.BeginRead method to ensure that the method is called only when the socket is open, however, it wasn't helpful because the checks such as TcpClient.Connected and Stream.CanRead always remain true despite the fact that the server has just gone down.

Exception Details
2021-05-13 13:54:31,105 [39] - FATAL WebSocketSharp: System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine. ---> System.Net.Sockets.SocketException: An established connection was aborted by the software in your host machine
at System.Net.Sockets.Socket.BeginReceive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, AsyncCallback callback, Object state)
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.FixedSizeReader.StartReading()
at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback asyncCallback, Object asyncState)
at System.Net.Security.SslStream.BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback asyncCallback, Object asyncState)
at WebSocketSharp.Ext.<>c__DisplayClass50_0.b__0(IAsyncResult ar)

Dominant language
C#
Stars
6.1k
Forks
1.7k
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from sta/websocket-sharp

All issues in sta/websocket-sharp

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.