sshnet / sshnet/SSH.NET

Memory Leak Issue When Streaming Data Over SSH

Open
#1,204 24 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
4.4k
Forks
993
Avg merge
9d 21h
Merged PRs (30d)
1

Description

Hello Renci.SshNet Team,

I have encountered a memory leak issue when utilizing the library to stream data over SSH in a .NET application. The memory consumption of the application significantly increases over time and does not get released back, even after the SSH connection is closed and disposed of.

Environment:

Renci.SshNet Version: 2023 , 2020.1 ,2020.2
.NET Version: 7
Steps to Reproduce:

Establish an SSH connection and create a shell stream.
Write a command to the shell stream and continuously read the output.
Monitor the memory usage of the application.
Expected Behavior:
Memory should be released back once the data is read from the SSH stream and especially after the SSH client is disconnected and disposed of.

Actual Behavior:
Memory usage continuously increases as data is read from the SSH stream and is not released back after the SSH client is disposed of.

Code Sample:

csharp

static async Task<bool> CheckIfLinuxAsync(string[] parts)
{
    string sshIp = parts[0];
    if (!int.TryParse(parts[1], out int sshPort) || sshPort <= 0 || sshPort > 65535)
    {
        return false;
    }
    string username = parts[2];
    string password = parts[3];
    string sshKey = $"{sshIp}:{sshPort}:{username}:{password}";

    try
    {
        var client = _sshClients.GetOrAdd(sshKey, key =>
        {
            var sshClient = new SshClient(sshIp, sshPort, username, password);
            sshClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(5);
            sshClient.Connect();
            return sshClient;
        });

        if (!client.IsConnected)
        {
            client.Connect();
        }

        using (var command = client.CreateCommand("uname -a"))
        {
            await Task.Run(() => command.Execute()).ConfigureAwait(false);
            return command.Result.Contains("Linux", StringComparison.OrdinalIgnoreCase);
        }
    }
    catch
    {
        _sshClients.TryRemove(sshKey, out var clientToRemove);
        clientToRemove?.Dispose();
        return false;
    }

Profiling Details:

The application's memory usage increases significantly over time.
The memory does not get reclaimed even after disconnecting and disposing of the SSH client.

Attachments:

Screenshot 2023-10-12 172504
Screenshot 2023-10-12 172833
Screenshot 2023-10-12 172526
Screenshot 2023-10-12 172543
Screenshot 2023-10-12 172626

Additional Context:
This issue is critical for our use case where the application needs to run for extended periods, streaming data over SSH. The memory leak leads to increased resource usage and can eventually cause the application to run out of memory.

Any insights or workarounds would be greatly appreciated while this issue is being investigated and resolved.

Thank you for your time and assistance!

Contributor guide

Open the contributing guide

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.

Research direction

Start by reducing the provided SshClient, shell-stream, and command-execution scenario to a reproducible memory profile, comparing usage while reading output and after disconnecting and disposing the client. Confirm the leak with the reported .NET 7 environment and profiling details; done means the reproduction no longer shows retained memory after the SSH client is disposed.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
networking
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.