Skip to content

Fix leaking ssh connections with VS Attach to Process#1552

Open
WardenGnaw wants to merge 1 commit intomainfrom
dev/waan/bug581
Open

Fix leaking ssh connections with VS Attach to Process#1552
WardenGnaw wants to merge 1 commit intomainfrom
dev/waan/bug581

Conversation

@WardenGnaw
Copy link
Member

This PR address the issue where every SSH PortSupplier AD7Port will always create a new SSH connection on the remote machine when the Attach to Process window opens and closes. This causes ports to be kept open until VS completly closes.

The changes here are to cache an existing connection if VS opens and closes the attach to process window.
Adds a ref count mechanism to ensure if you are debugging multiple processes on the same machine, it does not Clean the connection until all processes are done.

Testing:
Ran ss -t state established sport = :22 to see how many connections exist.

  • Open Attach to Process, Attach to C++ Process with GDB = One Connection
  • Attach to Process and Detach = 0 Connections
  • Attach, Detach, and Reattach = 1 Connection
  • Attach, Detach, and Reattach and Detach = 0 Connections
  • Attach x2 Processes = 2 Connections
  • Attach x2, Detach All = 0 Connections
  • Attach x2, Detach All, Reattach x2 = 2 Connections
  • Attach -> Detach -> Attach - >Detach -> Attach -> Detach = 0 Connections
  • Open Attach to Process and Closed Window = One connection lingers but Copilot insists issue is on the VS side, however current fix addresses the constant growing connection as described in SSH port supplier leaks connections #581

This PR address the issue where every SSH PortSupplier AD7Port will
always create a new SSH connection on the remote machine when the Attach
to Process window opens and closes. This causes ports to be kept open
until VS completly closes.

The changes here are to cache an existing connection if VS opens and
closes the attach to process window.
Adds a ref count mechanism to ensure if you are debugging multiple
processes on the same machine, it does not Clean the connection until
all processes are done.
if (port is IDebugUnixShellPort)
{
_unixPort = (IDebugUnixShellPort)port;
(_unixPort as IDebugPortCleanup)?.AddSessionRef();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this going to break other engines that use SSH transport?

finally
{
_connection = null;
Interlocked.Exchange(ref _sessionRefCount, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interlocked.Exchange(ref _sessionRefCount, 0);

I don't think you want this -- it should already be zero unless there is a race where we have already gotten another AddSessionRef, in which case you wouldn't want to blot that out

public void Clean()
{
try
if (Interlocked.Decrement(ref _sessionRefCount) > 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if

Assert that _sessionRefCount > 0?


lock (_lock)
{
try
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try

Is it possible for us to be shutting down and cleaning up at the same time on different threads? If so, I think we are going to have some race conditions here as:

  1. We allowed connections to be handed out before AddSessionRef is called, so those are subject to disposable at any time
  2. Clean can drop _sessionRefCount to zero, and then another thread can change it to 1, but this code doesn't check that. The easy way to fix this is to stop using Interlocked to change _sessionRefCount and instead increment/decrement it under the lock.

}
catch (Exception ex)
{
remoteSystem.Dispose();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remoteSystem.Dispose();

Should we just add a try/finally that will dispose it unless line 74 returns without throwing?

Copy link
Member

@gregg-miskelly gregg-miskelly left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM

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

Successfully merging this pull request may close these issues.

2 participants