FubarDevelopment / FtpServer

Portable FTP server written in .NET
http://fubardevelopment.github.io/FtpServer/
MIT License
477 stars 163 forks source link

FtpServer instance memory leak #84

Open yuanrui opened 4 years ago

yuanrui commented 4 years ago

In our project, I found remote camera use ftp client upload picture to server has several problem. The camera upload picture file used short connection, FtpServer class member "_connections" store all client connection info. When network disconnected or IFtpConnection Closed event not fired, the _connections will never release, then memory leak happened.

So, I thinked two ideas may be helpful.

  1. Use another thread to check active IFtpConnection is better. When checked some of them time out, then remove and dispose, it can be fix memory leak.
  2. Use "ConcurrentDictionary<IPEndPoint, FtpConnectionInfo>" instead of "ConcurrentDictionary<IFtpConnection, FtpConnectionInfo>", IPEndPoint store remote endpoint.

Here is my local DMP file debuged memory. memory leak DMP

fubar-coder commented 4 years ago

I guess that adding a connection timeout is the better solution here, because using the IPEndPoint would cause problems when the same application uses the same port for multiple connections. It sounds crazy, but it's possible. TcpClient.ExclusiveAddressUse

yuanrui commented 4 years ago

I set TcpClient ReceiveTimeout for 5 minutes in FtpServer class AddClientAsync method. But not work. The program after run several hours, connection can not release. STAT

yuanrui commented 4 years ago

I use this code to clear dead connection.

//DoClearConnection in a thread.
public void DoClearConnection()
{
    var lastCheckTime = DateTime.Now;
    while (! _stopClearConnection)
    {
        try
        {
            if ((DateTime.Now - lastCheckTime).TotalSeconds < 10)
            {
                Thread.Sleep(1000);
                continue;
            }
            lastCheckTime = DateTime.Now;

            var list = _connections.Where(m => (DateTime.Now - m.Value.ActiveTime).TotalMinutes > 1);
            if (!list.Any())
            {
                Thread.Sleep(1000);

                continue;
            }

            IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
            var activeConnections = ipProperties.GetActiveTcpConnections();

            Trace.Write($"Test Connection:{string.Join(",", list.Select(m => m.Key.ToString()))}");
            foreach (var item in list)
            {
                var socketAccessor = item.Value.Scope.ServiceProvider.GetRequiredService<TcpSocketClientAccessor>();
                var client = socketAccessor.TcpSocketClient;
                if (socketAccessor == null && client == null)
                {
                    RemoveConnection(item);
                    continue;
                }

                TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections().Where(x => x.LocalEndPoint.Port == this.Port && x.RemoteEndPoint.Equals(client.Client.RemoteEndPoint)).ToArray();

                if (tcpConnections != null && tcpConnections.Length > 0)
                {
                    TcpState stateOfConnection = tcpConnections.First().State;
                    if (stateOfConnection == TcpState.Established)
                    {
                        item.Value.ActiveTime = DateTime.Now;
                    }
                    else
                    {
                        RemoveConnection(item);
                    }
                }
                else
                {
                    RemoveConnection(item);
                }
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine($"Clear Ftp connection exception:{ex}");
        }                
    }
}

private void RemoveConnection(KeyValuePair<IPEndPoint, FtpConnectionInfo> pair)
{
    _connections.TryRemove(pair.Key, out var info);
    info.Scope.Dispose();
    _statistics.CloseConnection();
    Trace.Write($"Dispose Connection:{pair.Key.ToString()}");
}
fubar-coder commented 4 years ago

I'll publish a 3.1.1 soon, which includes configuration options for idle connection detection.

fubar-coder commented 4 years ago

3.1.1 is published and should be available soon (after the validation on nuget.org).

The important options for you are:

The timeout is also triggered when the network connection is still there, but the client did nothing for 5 minutes, no downloads or any FTP command.

yuanrui commented 4 years ago

OK, Thanks.

yuanrui commented 4 years ago

@fubar-coder It`s work. But the console report a fail message.

FubarDev.FtpServer.FtpServer:Error: The CancellationTokenSource has been disposed.

System.ObjectDisposedException: The CancellationTokenSource has been disposed.
   at System.Threading.CancellationTokenSource.ThrowObjectDisposedException()
   at System.Threading.CancellationTokenSource.get_Token()
   at FubarDev.FtpServer.FtpConnection.StartAsync() in D:\Work\FtpServer\src\FubarDev.FtpServer\FtpConnection.cs:line 301
   at FubarDev.FtpServer.FtpServer.AddClientAsync(TcpClient client) in D:\Work\FtpServer\src\FubarDev.FtpServer\FtpServer.cs:line 343
Waiting for 1 tasks
FubarDev.FtpServer.ServerCommandHandlers.SendResponseServerCommandHandler:Debug: 257 "/KK/192.168.1.51" created.
Collected data: 435744203139322E3136382E312E35310D0A
Task System.Threading.Tasks.ValueTask`1+ValueTaskSourceAsTask[System.Boolean] completed
FubarDev.FtpServer.FtpConnection:Debug: CWD 192.168.1.51
Waiting for 1 tasks

image

fubar-coder commented 4 years ago

Its as if the connection got closed while it was still about to get initialized/started.

Please try version 3.1.2-ci.16 from the following NuGet feed:

https://pkgs.dev.azure.com/fubar-development/ftp-server/_packaging/ftp-server-ci-builds%40Prerelease/nuget/v3/index.json

yuanrui commented 4 years ago

I used 3.1.2-ci.16, it will throw IO exception: thread quit or appliction request, abort IO operation. image

I set ConnectionInactivityCheckInterval 10 seconds, InactivityTimeout 3 minutes. But a few seconds later, the connection will be aborted. It`s look like InactivityTimeout not working.

FtpTimeoutException1

fubar-coder commented 4 years ago

I cannot reproduce this problem on my side. I tried the following:

My configuration file (appsettings.Development.json):

{
  "Logging": {
    "IncludeScopes": true,
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Information",
      "FubarDev.FtpServer.CommandHandlers.ListCommandHandler": "Trace",
      "FubarDev.FtpServer": "Trace"
    }
  },
  "server": {
    /* supported special addresses: "0.0.0.0", "::", "*" */
    "address": "*",
    /* Sets the interval between checks for expired connections in seconds. */
    "connectionInactivityCheckInterval": 10,
    /* Sets the inactivity timeout for connections in seconds. */
    "inactivityTimeout": 180
  },
  "backend": "in-memory"
}

I also tested it with TargetFramework set to netcoreapp3.0.

yuanrui commented 4 years ago

I forked last version repository for my local. I test in“QuickStart” project and changed some code. It look like not work.

FtpTimeoutTest

  TCP    192.168.1.108:2100     192.168.1.51:32796     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:32807     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:32847     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33051     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33152     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33263     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33278     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33849     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33933     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:33934     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:34286     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:34640     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:34858     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35299     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35302     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35342     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35444     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35600     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35601     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35750     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35793     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35974     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:35980     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36055     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36086     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36095     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36207     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36343     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36668     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36672     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36738     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36744     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36796     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:36820     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37007     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37038     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37178     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37383     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37462     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37673     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37814     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37920     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:37925     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:38000     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:38142     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:38169     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:38724     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:38849     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39035     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39105     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39340     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39518     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39565     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39675     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39728     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39888     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39991     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:39997     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40164     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40191     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40447     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40505     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40566     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:40659     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41042     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41079     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41204     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41209     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41231     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41257     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41361     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41500     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41610     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41714     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:41800     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:42017     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:42471     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:42716     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:42774     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:42967     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43123     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43191     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43198     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43247     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43257     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43286     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43493     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43679     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43898     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:43987     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44095     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44198     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44219     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44255     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44478     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44679     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44728     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44776     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:44828     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45090     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45201     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45306     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45361     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45451     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45460     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45548     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45550     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45624     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45741     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:45875     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46009     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46037     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46224     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46441     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46479     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46518     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46608     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46770     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46821     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:46862     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47129     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47330     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47354     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47563     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47569     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47643     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47665     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47745     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:47909     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48020     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48197     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48281     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48330     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48411     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48444     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48454     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48574     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48649     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48683     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48952     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48961     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:48988     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49011     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49042     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49049     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49104     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49295     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49320     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49379     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49454     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49466     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49501     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49597     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49694     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49781     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:49801     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50028     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50188     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50226     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50571     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50594     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50755     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50854     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50888     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:50920     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51121     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51642     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51730     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51791     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51867     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51870     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51897     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51953     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:51965     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52018     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52105     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52115     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52214     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52315     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52339     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52362     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52587     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52796     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52867     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:52993     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53106     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53110     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53409     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53424     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53443     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53459     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53584     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53795     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:53864     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:54343     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:54345     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:54540     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55105     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55188     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55252     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55318     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55390     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55399     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55517     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55580     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55740     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55761     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55804     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:55933     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56119     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56232     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56246     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56277     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56281     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56297     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56299     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56346     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56516     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56548     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56588     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56639     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56726     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56746     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56761     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:56927     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57016     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57090     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57220     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57224     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57303     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57358     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57474     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57493     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57708     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57769     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:57883     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:58076     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:58116     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:58960     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59191     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59242     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59326     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59407     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59553     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59562     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59589     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59595     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59606     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59614     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59727     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59841     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59911     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:59946     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60020     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60053     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60128     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60234     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60314     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60435     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60626     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60812     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.51:60893     CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.241:52321    ESTABLISHED     70372
  TCP    192.168.1.108:2100     192.168.1.241:52322    CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.241:52323    CLOSE_WAIT      70372
  TCP    192.168.1.108:2100     192.168.1.241:52325    CLOSE_WAIT      70372
yuanrui commented 4 years ago

By the way, I implement file system like in memory file system, in production environment has other problem: client over hundreds, memory used very high. And netstat has many TIME_WAIT. I have no idea, may be my code has some problem :-(

yuanrui commented 4 years ago

In my project. I find FtpConnectionAccessor AsyncLocal will keep original value in long time. so how to clean AsyncLocal value?

fubar-coder commented 4 years ago

That's a good hint. I'll take a look.

avonheimburg commented 4 years ago

We have noticed that same problem. We have a load balancer that, as a basic health check, simply checks if port 21 is open and, if it can connect to port 21 successfully, immediately closes it again. It does not issue any FTP command, it simply connects to the port and closes the connection immediately.

FtpServer leaves all those ports hanging in CLOSE_WAIT, leading to resource starvation and periodic container restarts.

victorperez2911 commented 3 years ago

@fubar-coder It`s work. But the console report a fail message.

FubarDev.FtpServer.FtpServer:Error: The CancellationTokenSource has been disposed.

System.ObjectDisposedException: The CancellationTokenSource has been disposed.
   at System.Threading.CancellationTokenSource.ThrowObjectDisposedException()
   at System.Threading.CancellationTokenSource.get_Token()
   at FubarDev.FtpServer.FtpConnection.StartAsync() in D:\Work\FtpServer\src\FubarDev.FtpServer\FtpConnection.cs:line 301
   at FubarDev.FtpServer.FtpServer.AddClientAsync(TcpClient client) in D:\Work\FtpServer\src\FubarDev.FtpServer\FtpServer.cs:line 343
Waiting for 1 tasks
FubarDev.FtpServer.ServerCommandHandlers.SendResponseServerCommandHandler:Debug: 257 "/KK/192.168.1.51" created.
Collected data: 435744203139322E3136382E312E35310D0A
Task System.Threading.Tasks.ValueTask`1+ValueTaskSourceAsTask[System.Boolean] completed
FubarDev.FtpServer.FtpConnection:Debug: CWD 192.168.1.51
Waiting for 1 tasks

image

Hello

I'm using the version 3.1.1 of the package, and I am getting exactly the error mentioned "The CancellationTokenSource has been disposed.", And when this occurs, the FTP Server is unavailable.

Any idea ?

fubar-coder commented 3 years ago

No, sorry. The server is currently in maintenance mode, but I'll start a rewrite of the FTP server using .NET 5.0 soon, which should have much less problems in this regard.

albertoVieiraNeto commented 2 years ago

Hi, i`m having this problem with the newest version available on nuget, after analysing the problem with dotMemory i narrowed down to the ConcurrentDictionary on the FTPServer Class here (line 38) the connections never seem to be removed from it, even after the inactive timeout has expired.

the funny thing is, the logout method on my custom membership provider is called, shouldn`t both be triggered together?