Skip to content

Commit 537f5f2

Browse files
Fix stdin locking on Unix platforms
Wait for Console.KeyAvailable before calling Console.ReadKey so getting cursor position doesn't block the thread.
1 parent 277e831 commit 537f5f2

File tree

4 files changed

+40
-1
lines changed

4 files changed

+40
-1
lines changed

PSReadLine.build.ps1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ task LayoutModule BuildMainModule, BuildMamlHelp, {
202202

203203
Copy-Item PSReadLine/bin/$Configuration/Microsoft.PowerShell.PSReadLine2.dll $targetDir
204204
Copy-Item PSReadLine/bin/$Configuration/System.Runtime.InteropServices.RuntimeInformation.dll $targetDir
205+
Copy-Item PSReadLine/bin/$Configuration/UnixConsoleEcho.dll $targetDir
206+
Copy-Item PSReadLine/bin/$Configuration/libdisablekeyecho.so $targetDir
207+
Copy-Item PSReadLine/bin/$Configuration/libdisablekeyecho.dylib $targetDir
205208

206209
# Copy module manifest, but fix the version to match what we've specified in the binary module.
207210
$version = (Get-ChildItem -Path $targetDir/Microsoft.PowerShell.PSReadLine2.dll).VersionInfo.FileVersion

PSReadLine/ConsoleLib.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,32 @@ public Encoding OutputEncoding
9797
set { try { Console.OutputEncoding = value; } catch { } }
9898
}
9999

100-
public ConsoleKeyInfo ReadKey() => Console.ReadKey(true);
100+
private void WaitForKeyAvailable()
101+
{
102+
// On Unix platforms input echo is on by default. If we wait for KeyAvailable without
103+
// disabling it, all input will be echoed.
104+
UnixConsoleEcho.InputEcho.Disable();
105+
try
106+
{
107+
while (!Console.KeyAvailable)
108+
{
109+
System.Threading.Thread.Sleep(50);
110+
}
111+
}
112+
finally
113+
{
114+
UnixConsoleEcho.InputEcho.Enable();
115+
}
116+
}
117+
118+
public ConsoleKeyInfo ReadKey()
119+
{
120+
// Wait for a key to be pressed before calling ReadKey to avoid locking stdin on
121+
// non-Windows platforms.
122+
WaitForKeyAvailable();
123+
return Console.ReadKey(true);
124+
}
125+
101126
public bool KeyAvailable => Console.KeyAvailable;
102127
public void SetWindowPosition(int left, int top) => Console.SetWindowPosition(left, top);
103128
public void SetCursorPosition(int left, int top) => Console.SetCursorPosition(left, top);

PSReadLine/PSReadLine.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151
<Reference Include="Microsoft.CSharp" />
5252
<Reference Include="System.Data" />
5353
<Reference Include="System.Xml" />
54+
<Reference Include="UnixConsoleEcho, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
55+
<HintPath>packages\UnixConsoleEcho.0.1.0\lib\net461\UnixConsoleEcho.dll</HintPath>
56+
</Reference>
5457
</ItemGroup>
5558
<ItemGroup>
5659
<Compile Include="AssemblyInfo.cs" />
@@ -121,6 +124,13 @@
121124
..\..\CopyDLL.cmd $(TargetPath)
122125
)</PostBuildEvent>
123126
</PropertyGroup>
127+
<Import Project="packages\UnixConsoleEcho.0.1.0\build\net461\UnixConsoleEcho.targets" Condition="Exists('packages\UnixConsoleEcho.0.1.0\build\net461\UnixConsoleEcho.targets')" />
128+
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
129+
<PropertyGroup>
130+
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
131+
</PropertyGroup>
132+
<Error Condition="!Exists('packages\UnixConsoleEcho.0.1.0\build\net461\UnixConsoleEcho.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\UnixConsoleEcho.0.1.0\build\net461\UnixConsoleEcho.targets'))" />
133+
</Target>
124134
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
125135
Other similar extension points exist, see Microsoft.Common.targets.
126136
<Target Name="BeforeBuild">

PSReadLine/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
<packages>
33
<package id="Microsoft.PowerShell.5.ReferenceAssemblies" version="1.0.0" targetFramework="net461" />
44
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net461" />
5+
<package id="UnixConsoleEcho" version="0.1.0" targetFramework="net461" />
56
</packages>

0 commit comments

Comments
 (0)