Make experimental feature PSRemotingSSHTransportErrorHandling stable (#18046) (#18085)

This commit is contained in:
Aditya Patwardhan
2022-09-14 11:18:40 -07:00
committed by GitHub
parent d1bd7eb841
commit ec7bb207e9
4 changed files with 16 additions and 91 deletions
-1
View File
@@ -2,6 +2,5 @@
"PSCommandNotFoundSuggestion",
"PSLoadAssemblyFromNativeCode",
"PSNativeCommandErrorActionPreference",
"PSRemotingSSHTransportErrorHandling",
"PSSubsystemPluginModel"
]
-1
View File
@@ -2,6 +2,5 @@
"PSCommandNotFoundSuggestion",
"PSLoadAssemblyFromNativeCode",
"PSNativeCommandErrorActionPreference",
"PSRemotingSSHTransportErrorHandling",
"PSSubsystemPluginModel"
]
@@ -22,7 +22,6 @@ namespace System.Management.Automation
internal const string EngineSource = "PSEngine";
internal const string PSNativeCommandErrorActionPreferenceFeatureName = "PSNativeCommandErrorActionPreference";
internal const string PSRemotingSSHTransportErrorHandling = "PSRemotingSSHTransportErrorHandling";
#endregion
@@ -116,10 +115,7 @@ namespace System.Management.Automation
description: "Expose an API to allow assembly loading from native code"),
new ExperimentalFeature(
name: PSNativeCommandErrorActionPreferenceFeatureName,
description: "Native commands with non-zero exit codes issue errors according to $ErrorActionPreference when $PSNativeCommandUseErrorActionPreference is $true"),
new ExperimentalFeature(
name: PSRemotingSSHTransportErrorHandling,
description: "Removes the SSH remoting transport stdErr stream message handling as terminating errors, and instead just writes error messages to console.")
description: "Native commands with non-zero exit codes issue errors according to $ErrorActionPreference when $PSNativeCommandUseErrorActionPreference is $true")
};
EngineExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(engineFeatures);
@@ -1819,50 +1819,30 @@ namespace System.Management.Automation.Remoting.Client
{
string error;
if (ExperimentalFeature.IsEnabled(ExperimentalFeature.PSRemotingSSHTransportErrorHandling))
// Blocking read from StdError stream
error = reader.ReadLine();
if (error == null)
{
// Blocking read from StdError stream
error = reader.ReadLine();
if (error == null)
{
// Stream is closed unexpectedly.
throw new PSInvalidOperationException(RemotingErrorIdStrings.SSHAbruptlyTerminated);
}
if (error.Length == 0)
{
// Ignore
continue;
}
try
{
// Messages in error stream from ssh are unreliable, and may just be warnings or
// banner text.
// So just report the messages but don't act on them.
System.Console.WriteLine(error);
}
catch (IOException)
{ }
continue;
// Stream is closed unexpectedly.
throw new PSInvalidOperationException(RemotingErrorIdStrings.SSHAbruptlyTerminated);
}
error = ReadError(reader);
if (error.Length == 0)
{
// Ignore
continue;
}
// Any SSH client error results in a broken session.
PSRemotingTransportException psrte = new PSRemotingTransportException(
PSRemotingErrorId.IPCServerProcessReportedError,
RemotingErrorIdStrings.IPCServerProcessReportedError,
StringUtil.Format(RemotingErrorIdStrings.SSHClientEndWithErrorMessage, error));
HandleSSHError(psrte);
try
{
// Messages in error stream from ssh are unreliable, and may just be warnings or
// banner text.
// So just report the messages but don't act on them.
System.Console.WriteLine(error);
}
catch (IOException)
{ }
}
}
catch (ObjectDisposedException)
@@ -1888,55 +1868,6 @@ namespace System.Management.Automation.Remoting.Client
CloseConnection();
}
private static string ReadError(StreamReader reader)
{
// Blocking read from StdError stream
string error = reader.ReadLine();
if (error == null)
{
// Stream is closed unexpectedly.
throw new PSInvalidOperationException(RemotingErrorIdStrings.SSHAbruptlyTerminated);
}
if ((error.Length == 0) ||
error.Contains("WARNING:", StringComparison.OrdinalIgnoreCase))
{
// Handle as interactive warning message
Console.WriteLine(error);
return string.Empty;
}
// SSH may return a multi-line error message.
// The StdError pipe stream is open ended causing StreamReader read operations to block
// if there is no incoming data. Since we don't know how many error message lines there
// will be we use an asynchronous read with timeout to prevent blocking indefinitely.
System.Text.StringBuilder sb = new Text.StringBuilder(error);
var running = true;
while (running)
{
try
{
var task = reader.ReadLineAsync();
if (task.Wait(1000) && (task.Result != null))
{
sb.Append(Environment.NewLine);
sb.Append(task.Result);
}
else
{
running = false;
}
}
catch (Exception)
{
running = false;
}
}
return sb.ToString();
}
private void StartReaderThread(
StreamReader reader)
{