Runtime: System.Console: KeyAvailable returns False for Backspace on Linux

Created on 10 Apr 2019  路  9Comments  路  Source: dotnet/runtime

OS Version: Debian GNU/Linux 8 (jessie) x86_64-linux-gnu

Tested .NET versions:

  • 2.1.300
  • 3.0.100-preview3-010431
    On all specified versions the issue was reproducible.

Summary
When using the Console.KeyAvailable property in order to implement non-blocking console input, the property is not being set to true when Backspace is pressed. The same code (see example) when being run on Windows works as intended.

Example
Here is a simple example which reproduces the issue on my machine:

 ConsoleKeyInfo key = new ConsoleKeyInfo();
 do
 {
    if (Console.KeyAvailable)
    {
        key = Console.ReadKey(true);
        Console.WriteLine($"You pressed: {key.Key}");
    }
    System.Threading.Thread.Sleep(100);
 } while (key.Key != ConsoleKey.Escape);

The following code, however, works as intended both on Linux and Windows (the difference that the IO is blocking here, which is unacceptable for my use case, sadly) - the Backspace key is being handled:

 ConsoleKeyInfo key = new ConsoleKeyInfo();
 do
 {
    key = Console.ReadKey(true);
    Console.WriteLine($"You pressed: {key.Key}");
 } while (key.Key != ConsoleKey.Escape);

I'm currently implementing a ncurses-like terminal GUI library, and I'm running my logic in a loop, so this issue is blocking me from implementing input handling for text input.

If any additional info is needed, I'll happily provide it. Thanks for creating such an awesome platform to develop on :wink:

area-System.Console

Most helpful comment

@tmds, what was the issue and how did that fix it?

Console.KeyAvailable doesn't return stdin is readable when the user presses backspace.

Before https://github.com/dotnet/corefx/pull/35621 we were in canonical mode while the user was pressing the key (during the Thread.Sleep). In canonical mode the backspace gets processed by the terminal.

All 9 comments

Thanks @RaZeR-RBI. Any interest in debugging a bit? The more we understand the more likely a fix can happen sooner.

Cc @tmds

This is fixed by https://github.com/dotnet/corefx/pull/35621.
@RaZeR-RBI this isn't yet in a 3.0 preview release, but you can try using a daily build from https://github.com/dotnet/core-sdk/blob/master/README.md#installers-and-binaries

This is fixed by dotnet/corefx#35621.

@tmds, what was the issue and how did that fix it?

@tmds, what was the issue and how did that fix it?

Console.KeyAvailable doesn't return stdin is readable when the user presses backspace.

Before https://github.com/dotnet/corefx/pull/35621 we were in canonical mode while the user was pressing the key (during the Thread.Sleep). In canonical mode the backspace gets processed by the terminal.

This is fixed by dotnet/corefx#35621.
@RaZeR-RBI this isn't yet in a 3.0 preview release, but you can try using a daily build from https://github.com/dotnet/core-sdk/blob/master/README.md#installers-and-binaries

Downloaded the daily build, everything works now. Thanks!

In canonical mode the backspace gets processed by the terminal.

Got it. That's what I was missing.

For those who are looking for a workaround for the current version, here is a sample code (without error handling and other stuff, you should get the idea):

private struct pollfd
{
    public int fd;
    public short events;
    public short revents;
};

private const int POLLIN = 0x0001;
private const int STDIN_FILENO = 0;

[DllImport("libc")]
private static extern int poll(ref pollfd fds, uint nfds, int timeout);

// call this at application start
public static void SetTerminalAttributes() =>
    Process.Start("stty", "-echo -icanon min 1 time 0").WaitForExit();

// call this when needed
public static bool KeyAvailable()
{
    var fd = new pollfd()
    {
        fd = STDIN_FILENO,
        events = POLLIN
    };
    var result = poll(ref fd, 1, 0);
    return result > 0;
}

It can also be used as a workaround for a related dotnet/corefx#25916 issue. Of course, this will mess up with children process echoing (I don't use them in my project, though), as stated here. And of course, don't forget to restore terminal settings at application exit :wink:

Thanks @tmds, and @RaZer-RBI for confirming.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

omariom picture omariom  路  3Comments

EgorBo picture EgorBo  路  3Comments

aggieben picture aggieben  路  3Comments

bencz picture bencz  路  3Comments

matty-hall picture matty-hall  路  3Comments