-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Version Information
Version of Akka.NET? dev branch
Which Akka.NET Modules? Akka.IO
Describe the bug
The way TcpListener is accepting new connection is buggy. JVM managed TCP sockets through the nio channel selector pattern while we're doing it closer to bare metal by requesting actual sockets for each incoming connection.
The way it is done in JVM is to use an accepting limit that is being decremented each time a new channel is created, in our case we used SocketAsyncEventArgs as an async non-blocking way of accepting connections (https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/IO/TcpListener.cs#L68-L79).
- In JVM all channels are passed to the TcpConnection class and have its lifetime managed by it, in ours, SAEA are stored inside an array and they are supposed to be disposed on TcpListener
PostStop
. But they're not. This array is being overwritten when aResumeAccepting
command is received, possibly creating a memory leak (https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/IO/TcpListener.cs#L100-L103) - Instead of being limited by the accept number, we're reusing SAEA objects (which is a really bad idea) and kept accepting new connections when new socket connections were made (https://github.com/akkadotnet/akka.net/blob/dev/src/core/Akka/IO/TcpListener.cs#L90-L97)
We can probably improve this this by ditching SAEA and use _socket.AcceptAsync(null, cancellationToken)
instead. The SAEA would be managed by the method and all pending accept command can be cancelled using the token.