Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using async methods of TlsStream causes ThreadPool starvation #481

Open
jivkopiskov opened this issue Aug 28, 2023 · 0 comments
Open

Using async methods of TlsStream causes ThreadPool starvation #481

jivkopiskov opened this issue Aug 28, 2023 · 0 comments

Comments

@jivkopiskov
Copy link

The current implementation of the Tls.Stream async API (BeginRead, ReadAsync, etc) just schedules a task and calls the blocking non-async Read.
This causes most of the thread pool threads to be blocked with a stack similar to this one:

  System.Net.Sockets.il!Interop+Winsock.recv(class System.Net.Sockets.SafeSocketHandle,unsigned int8*,int32,value class System.Net.Sockets.SocketFlags)
  System.Net.Sockets.il!System.Net.Sockets.SocketPal.Receive(class System.Net.Sockets.SafeSocketHandle,value class System.Span`1<unsigned int8>,value class System.Net.Sockets.SocketFlags,int32&)
  System.Net.Sockets.il!System.Net.Sockets.Socket.Receive(unsigned int8[],int32,int32,value class System.Net.Sockets.SocketFlags,value class System.Net.Sockets.SocketError&)
  System.Net.Sockets.il!System.Net.Sockets.NetworkStream.Read(unsigned int8[],int32,int32)
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.RecordStream+Record.FillTo(class System.IO.Stream,int32)
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.RecordStream+Record.ReadHeader(class System.IO.Stream)
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.RecordStream.ReadRecord()
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.TlsProtocol.SafeReadRecord()
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.TlsProtocol.ReadApplicationData(unsigned int8[],int32,int32)
  BouncyCastle.Crypto!Org.BouncyCastle.Tls.TlsStream.Read(unsigned int8[],int32,int32)
  System.Private.CoreLib.il!System.IO.Stream+<>c.<BeginReadInternal>b__38_0(class System.Object)
  System.Private.CoreLib.il!System.Threading.Tasks.Task`1[System.Int32].InnerInvoke()
  System.Private.CoreLib.il!System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(class System.Threading.Thread,class System.Threading.ExecutionContext,class System.Threading.ContextCallback,class System.Object)
  System.Private.CoreLib.il!System.Threading.Tasks.Task.ExecuteWithThreadLocal(class System.Threading.Tasks.Task&,class System.Threading.Thread)
  System.Private.CoreLib.il!System.Threading.ThreadPoolWorkQueue.Dispatch()
  System.Private.CoreLib.il!System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()

Is there a way to use the TlsStream in a non-blocking way? As far as I understand, BC would need to add proper implementation of the async apis for the TlsStream, TlsProtocol and RecordStream, which will use the Async APIs of the provided inner stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant