dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.82k stars 4.61k forks source link

.net 8 Console.ReadKey : Better support for return Ctrl-Z, and setting SIGSTOP #91709

Open kjpgit opened 11 months ago

kjpgit commented 11 months ago

When a full screen / raw terminal app like vim gets a ctrl-z, it reads it as a keypress, not a signal. This can be done with the right tcsetattr() settings:

t.c_cc[Libc.VSUSP] = 0; Will stop SIGTSTP from coming as a signal, but instead it comes in as \x1A key.

But more importantly, the app then gets a chance to restore the terminal to the 'main' shell screen, before suspending itself with a SIGSTOP (I think). Basically, gracefully set the terminal back before suspending.

In .net 8, I can override the SIGTSTP (Terminal Stop) signal, and set the console back to the 'main' terminal buffer by sending a "[?1049l", but I can't send myself a SIGSTOP.

At least, not without bringing in Mono.Posix, and that seems to have additional complications with AOT compilation. (Missing DLL)

Ideally, .net knows how to gracefully suspend a console app -- taking it away from and back to the alternate terminal screen -- without additional libraries.

ghost commented 11 months ago

Tagging subscribers to this area: @dotnet/area-system-console See info in area-owners.md if you want to be subscribed.

Issue Details
I'm trying to capture ctrl-z as a keypress, not a signal. This can be done with the right tcsetattr() settings. For example, vim does it, I believe, to restore the "main" terminal window, then suspend itself. I tried disabling the signal (PosixSignalRegistration.Create(PosixSignal.SIGTSTP, ..) both with and without "Cancel", but I still don't see a ctrl-z. My suggestion, is if the user is trying to disable SIGTSTP, then update tcsetattr() so it gets returned as a keypress: `t.c_cc[Libc.VSUSP] = 0;` Will stop SIGTSTP from coming as a signal, but instead it comes in as \x1A key.
Author: kjpgit
Assignees: -
Labels: `area-System.Console`
Milestone: -
kjpgit commented 11 months ago

This is a truly ugly hack, using "sh" to send myself a SIGSTOP. Ideally the runtime has support for sending a SIGSTOP.

            if (evt.signal == PosixSignal.SIGWINCH || evt.signal == PosixSignal.SIGCONT) {
                console.SetAlternateScreen(true);   // Sends ?1049h
                Redraw();
            }
            if (evt.signal == PosixSignal.SIGTSTP) {
                Log.Info("moving back to main terminal screen");
                console.SetAlternateScreen(false);  // Sends ?1049l
                console.SetNormalColorAndEnableCursor();
                console.Flush();
                var pi = new ProcessStartInfo("sh");
                pi.ArgumentList.Add("-c");
                pi.ArgumentList.Add("kill -STOP $PPID; echo stopped >> /tmp/stop.log");
                Process.Start(pi);
            }