Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit f2aa64b

Browse files
committed
Merge pull request #1928 from stephentoub/cancelkeypress_unix
Implement Console.CancelKeyPress on Unix
2 parents 6226545 + ce06190 commit f2aa64b

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Microsoft.Win32.SafeHandles;
5+
using System;
6+
using System.Runtime.InteropServices;
7+
8+
internal partial class Interop
9+
{
10+
internal partial class libcoreclr
11+
{
12+
internal const int CTRL_C_EVENT = 0;
13+
internal const int CTRL_BREAK_EVENT = 1;
14+
15+
internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
16+
internal const int ERROR_INVALID_PARAMETER = 0x57;
17+
18+
internal delegate bool ConsoleCtrlHandlerRoutine(int controlType);
19+
20+
[DllImport(Libraries.LibCoreClr, SetLastError = true)]
21+
internal static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandlerRoutine handler, bool addOrRemove);
22+
}
23+
}

src/System.Console/src/System.Console.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@
136136
<Compile Include="$(CommonPath)\Interop\Unix\libcoreclr\Interop.GetFileInformation.cs">
137137
<Link>Common\Interop\Unix\Interop.GetFileInformation.cs"</Link>
138138
</Compile>
139+
<Compile Include="$(CommonPath)\Interop\Unix\libcoreclr\Interop.SetConsoleCtrlHandler.cs">
140+
<Link>Common\Interop\Unix\Interop.SetConsoleCtrlHandler.cs"</Link>
141+
</Compile>
139142
</ItemGroup>
140143
<ItemGroup Condition=" '$(TargetsLinux)' == 'true' ">
141144
<Compile Include="$(CommonPath)\Interop\Linux\Interop.Errors.cs">

src/System.Console/src/System/ConsolePal.Unix.cs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,15 +1173,34 @@ public void Clear()
11731173

11741174
internal sealed class ControlCHandlerRegistrar
11751175
{
1176-
internal void Register()
1176+
private readonly Interop.libcoreclr.ConsoleCtrlHandlerRoutine _handler;
1177+
private bool _handlerRegistered;
1178+
1179+
internal ControlCHandlerRegistrar()
11771180
{
1178-
// UNIXTODO: Install SIGINT signal handler.
1181+
_handler = new Interop.libcoreclr.ConsoleCtrlHandlerRoutine(c =>
1182+
(c == Interop.libcoreclr.CTRL_C_EVENT || c == Interop.libcoreclr.CTRL_BREAK_EVENT) &&
1183+
Console.HandleBreakEvent(c == Interop.libcoreclr.CTRL_C_EVENT ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak));
11791184
}
11801185

1181-
internal void Unregister()
1186+
internal void Register() { RegisterOrUnregister(true); }
1187+
1188+
internal void Unregister() { RegisterOrUnregister(false); }
1189+
1190+
private void RegisterOrUnregister(bool register)
11821191
{
1183-
// UNIXTODO: remove handler.
1192+
Debug.Assert(register == !_handlerRegistered);
1193+
if (!Interop.libcoreclr.SetConsoleCtrlHandler(_handler, register))
1194+
{
1195+
int error = Marshal.GetLastWin32Error(); // Win32 error code from coreclr PAL, not a Unix errno value
1196+
throw Interop.GetExceptionForIoErrno(
1197+
error == Interop.libcoreclr.ERROR_INVALID_PARAMETER ? Interop.Errors.EINVAL :
1198+
error == Interop.libcoreclr.ERROR_NOT_ENOUGH_MEMORY ? Interop.Errors.ENOMEM :
1199+
Interop.Errors.EIO);
1200+
}
1201+
_handlerRegistered = register;
11841202
}
11851203
}
1204+
11861205
}
1187-
}
1206+
}

0 commit comments

Comments
 (0)