Fix hang when reading stdin from ruby

This is a workaround for a full clr issue that causes a hang when calling PowerShell from ruby.
They use named pipes instead of anonymous pipes, and for some reason that triggers the hang.
This commit is contained in:
Jason Shirk (POWERSHELL)
2016-09-26 11:22:28 -07:00
parent 1913244fad
commit 07b0964be4
4 changed files with 27 additions and 5 deletions
@@ -3467,6 +3467,9 @@ namespace Microsoft.PowerShell
[DllImport(PinvokeDllNames.GetLargestConsoleWindowSizeDllName, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern COORD GetLargestConsoleWindowSize(NakedWin32Handle consoleOutput);
[DllImport(PinvokeDllNames.GetStdHandleDllName, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr GetStdHandle(int handleId);
[DllImport(PinvokeDllNames.ReadConsoleDllName, SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool ReadConsole
(
@@ -2868,6 +2868,25 @@ namespace Microsoft.PowerShell
private System.Threading.Thread _breakHandlerThread;
private bool _isDisposed;
internal ConsoleHostUserInterface ui;
#if CORECLR
internal Lazy<TextReader> ConsoleIn { get; } = new Lazy<TextReader>(() => Console.In);
#else
internal Lazy<TextReader> ConsoleIn { get; } = new Lazy<TextReader>(() =>
{
// This is a workaround for a full clr issue that causes a hang when calling PowerShell from ruby.
// They use named pipes instead of anonymous pipes, and for some reason that triggers a hang
// reading from Console.In.
var inputHandle = ConsoleControl.NativeMethods.GetStdHandle(-10);
var s = new FileStream(new ConsoleHandle(inputHandle, false), FileAccess.Read);
uint codePage = (uint) ConsoleControl.NativeMethods.GetConsoleCP();
Encoding encoding = Encoding.GetEncoding((int) codePage);
return TextReader.Synchronized(new StreamReader(s, encoding, false));
});
#endif
private string _savedWindowTitle = "";
private Version _ver = PSVersionInfo.PSVersion;
private int _exitCodeFromRunspace;
@@ -1560,9 +1560,10 @@ namespace Microsoft.PowerShell
sb.Append('\n');
}
var consoleIn = _parent.ConsoleIn.Value;
while (true)
{
var inC = Console.In.Read();
var inC = consoleIn.Read();
if (inC == -1)
{
// EOF - we return null which tells our caller to exit
@@ -1577,10 +1578,10 @@ namespace Microsoft.PowerShell
if (c == '\r')
{
// Treat as newline, but consume \n if there is one.
if (Console.In.Peek() == '\n')
if (consoleIn.Peek() == '\n')
{
if (!NoPrompt) Console.Out.Write('\n');
Console.In.Read();
consoleIn.Read();
}
break;
}
@@ -212,8 +212,7 @@ namespace Microsoft.PowerShell
if ((options & ExecutionOptions.ReadInputObjects) > 0 && Console.IsInputRedirected)
{
// read input objects from stdin
WrappedDeserializer des = new WrappedDeserializer(_parent.InputFormat, "Input", Console.In);
WrappedDeserializer des = new WrappedDeserializer(_parent.InputFormat, "Input", _parent.ConsoleIn.Value);
while (!des.AtEnd)
{
object o = des.Deserialize();