Skip to content

[release/v7.5] Close pipe client handles after creating the child ssh process#26822

Merged
daxian-dbw merged 1 commit intoPowerShell:release/v7.5from
daxian-dbw:backport/release/v7.5/26491-9ee3c61c2
Feb 14, 2026
Merged

[release/v7.5] Close pipe client handles after creating the child ssh process#26822
daxian-dbw merged 1 commit intoPowerShell:release/v7.5from
daxian-dbw:backport/release/v7.5/26491-9ee3c61c2

Conversation

@daxian-dbw
Copy link
Member

Backport of #26491 to release/v7.5

Triggered by @daxian-dbw on behalf of @daxian-dbw

Original CL Label: CL-General

/cc @PowerShell/powershell-maintainers

Impact

REQUIRED: Choose either Tooling Impact or Customer Impact (or both). At least one checkbox must be selected.

Tooling Impact

  • Required tooling change
  • Optional tooling change (include reasoning)

Customer Impact

  • Customer reported
  • Found internally

Fixes hang when attempting SSH connections to non-existent hosts on Windows. Affects users using Invoke-Command and New-PSSession with SSH.

Regression

REQUIRED: Check exactly one box.

  • Yes
  • No

This is not a regression.

Testing

New tests added to verify no hang occurs. Successfully tested in 7.6 release. Fixes reported customer issues #25203 and #26228.

Risk

REQUIRED: Check exactly one box.

  • High
  • Medium
  • Low

Fixes critical hang issue in SSH remoting on Windows. Changes are scoped to SSH connection setup. Successfully backported to 7.6 branch.

@daxian-dbw daxian-dbw added the CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log label Feb 13, 2026
Copilot AI review requested due to automatic review settings February 13, 2026 23:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Backport to release/v7.5 of the Windows SSH remoting hang fix by ensuring the parent process closes the client-side pipe handles after spawning ssh.exe, so the stdout/stderr reader threads can terminate when ssh.exe exits.

Changes:

  • Dispose Win32 STARTUPINFO after CreateProcess to close inherited pipe client handles in the parent process.
  • Minor cleanup to remove redundant namespace qualifications in SSH transport code paths.
  • Add Pester coverage to validate SSH remoting cmdlets don’t hang when connecting to a non-existent host.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
test/powershell/engine/Remoting/SSHRemotingCmdlets.Tests.ps1 Adds CI test cases intended to catch regressions where SSH remoting could hang on failed connections.
src/System.Management.Automation/engine/remoting/fanin/OutOfProcTransportManager.cs Small refactors/cleanup for process lookup and error-prefix handling in SSH transport read loops.
src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs Core fix: closes parent pipe client handles by disposing startup info after creating the ssh.exe child process; includes minor cleanup and a dispose bugfix in an exception path.

Comment on lines +74 to +92
Describe "No hangs when host doesn't exist" -Tags "CI" {
$testCases = @(
@{
Name = 'Verifies no hang for New-PSSession with non-existing host name'
ScriptBlock = { New-PSSession -HostName "test-notexist" -UserName "test" -ErrorAction Stop }
FullyQualifiedErrorId = 'PSSessionOpenFailed'
},
@{
Name = 'Verifies no hang for Invoke-Command with non-existing host name'
ScriptBlock = { Invoke-Command -HostName "test-notexist" -UserName "test" -ScriptBlock { 1 } -ErrorAction Stop }
FullyQualifiedErrorId = 'PSSessionStateBroken'
}
)

It "<Name>" -TestCases $testCases {
param ($ScriptBlock, $FullyQualifiedErrorId)

$ScriptBlock | Should -Throw -ErrorId $FullyQualifiedErrorId -ExceptionType 'System.Management.Automation.Remoting.PSRemotingTransportException'
}
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

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

The new hang-regression tests rely on a specific -ErrorId value, but earlier in this same file the SSH open failure error id is noted as platform-dependent (matched via -Match 'PSSessionOpenFailed'). To avoid flaky CI failures, consider using a wildcard/regex match for the error id (or asserting on exception type/message instead), and add an explicit short timeout around the SSH invocation so a reintroduced hang fails quickly rather than stalling the whole test run. Also consider using a reserved non-existent domain (e.g. *.invalid) instead of test-notexist to reduce the chance of accidental DNS resolution in some environments.

Copilot uses AI. Check for mistakes.
@daxian-dbw daxian-dbw merged commit f9e3b97 into PowerShell:release/v7.5 Feb 14, 2026
22 checks passed
@daxian-dbw daxian-dbw deleted the backport/release/v7.5/26491-9ee3c61c2 branch February 14, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CL-General Indicates that a PR should be marked as a general cmdlet change in the Change Log

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants