-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Epic: Make input and output mode process state instead of global state #4954
Comments
I attempted to dissect our input queue during Hackathon. Here's my notes inside the bufferThings that happen during WRITE
Things that happen during READ
During FLUSH
outside the buffer
ENQUEUED EVENTS
|
The concerns for handling partials are spread across three classes, some of which are already process-local state. If you do a LINE_INPUT and receive multiple lines, there's a chance that partial lines will be saved against your process data. If you do a raw event input and get partials, they're saved globally on the queue. Neither of these are cleared by a FLUSH. Rearchitecting our input records to do translation at READ time instead of WRITE time will be difficult, but will ensure more consistent results (one process can't read half of a VT sequence, the clipboard would be a single event so that two processes couldn't both read half the clipboard data, etc.) and when an event translates to multiple outputs that don't fit they'll be enqueued per-handle. |
Windows provides the `ENABLE_VIRTUAL_TERMINAL_INPUT` flag for TTY input streams as a companion flag to `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, which libuv is already setting for TTY output streams. Setting this flag lets the terminal emulator perform some of the processing that libuv already currently does for input events, but most notably enables receiving control sequences that are otherwise entirely unavailable, e.g. for bracketed paste (which the Node.js readline implementation added basic support for in nodejs/node@87af913b66eab78088acfd). Unfortunately, there is a non-trivial downside to this, which I have not been able to fully resolve; specifically, not all shells reset this mode when an application exits. For example, when running a Node.js program with this flag enabled inside of PowerShell in Windows terminal, if the application exits while in raw TTY input mode, neither the shell nor the terminal emulator reset this flag, rendering the input stream unusable. While there's general awareness of the problem that console state is global state rather than per-process (same as on UNIX platforms), it seems that applications like PowerShell aren't expecting to need to unset this flag on the input stream, only its output counterpart (e.g. https://github.com/PowerShell/PowerShell/blob/4e7942135f998ab40fd3ae298b020e161a76d4ef/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs#L1156). If libuv should add support for automatically resetting TTY state when the application exits, that would make sense to me; unfortunately, I don't know if there's an easy way to support this. For now, I am proposing this change knowing that it requires applications to be diligent about cleaning up TTY state, and am happy to take suggestions for improvements on this approach. Refs: nodejs/node@87af913 Refs: microsoft/terminal#4954
Windows provides the `ENABLE_VIRTUAL_TERMINAL_INPUT` flag for TTY input streams as a companion flag to `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, which libuv is already setting for TTY output streams. Setting this flag lets the terminal emulator perform some of the processing that libuv already currently does for input events, but most notably enables receiving control sequences that are otherwise entirely unavailable, e.g. for bracketed paste (which the Node.js readline implementation added basic support for in nodejs/node@87af913b66eab78088acfd). libuv currently already provides translations for key events to control sequences, i.e. what this mode is intended to provide, but libuv does not and cannot translate all such events. Since the control sequences differ from the ones that Windows has chosen to standardize on, and applications may not be expecting this change, this is opt-in for now (but ideally will be the default behavior starting in libuv v2.x, should that ever happen). Another downside of this change is that not all shells reset this mode when an application exits. For example, when running a Node.js program with this flag enabled inside of PowerShell in Windows terminal, if the application exits while in raw TTY input mode, neither the shell nor the terminal emulator reset this flag, rendering the input stream unusable. While there's general awareness of the problem that console state is global state rather than per-process (same as on UNIX platforms), it seems that applications like PowerShell aren't expecting to need to unset this flag on the input stream, only its output counterpart (e.g. https://github.com/PowerShell/PowerShell/blob/4e7942135f998ab40fd3ae298b020e161a76d4ef/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs#L1156). Hence, `uv_tty_reset_mode()` is extended to reset the terminal to its original state if the new mode is being used. Refs: nodejs/node@87af913 Refs: microsoft/terminal#4954
Windows provides the `ENABLE_VIRTUAL_TERMINAL_INPUT` flag for TTY input streams as a companion flag to `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, which libuv is already setting for TTY output streams. Setting this flag lets the terminal emulator perform some of the processing that libuv already currently does for input events, but most notably enables receiving control sequences that are otherwise entirely unavailable, e.g. for bracketed paste (which the Node.js readline implementation added basic support for in nodejs/node@87af913b66eab78088acfd). libuv currently already provides translations for key events to control sequences, i.e. what this mode is intended to provide, but libuv does not and cannot translate all such events. Since the control sequences differ from the ones that Windows has chosen to standardize on, and applications may not be expecting this change, this is opt-in for now (but ideally will be the default behavior starting in libuv v2.x, should that ever happen). Another downside of this change is that not all shells reset this mode when an application exits. For example, when running a Node.js program with this flag enabled inside of PowerShell in Windows terminal, if the application exits while in raw TTY input mode, neither the shell nor the terminal emulator reset this flag, rendering the input stream unusable. While there's general awareness of the problem that console state is global state rather than per-process (same as on UNIX platforms), it seems that applications like PowerShell aren't expecting to need to unset this flag on the input stream, only its output counterpart (e.g. https://github.com/PowerShell/PowerShell/blob/4e7942135f998ab40fd3ae298b020e161a76d4ef/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs#L1156). Hence, `uv_tty_reset_mode()` is extended to reset the terminal to its original state if the new mode is being used. Refs: nodejs/node@87af913 Refs: microsoft/terminal#4954
Windows provides the `ENABLE_VIRTUAL_TERMINAL_INPUT` flag for TTY input streams as a companion flag to `ENABLE_VIRTUAL_TERMINAL_PROCESSING`, which libuv is already setting for TTY output streams. Setting this flag lets the terminal emulator perform some of the processing that libuv already currently does for input events, but most notably enables receiving control sequences that are otherwise entirely unavailable, e.g. for bracketed paste (which the Node.js readline implementation added basic support for in nodejs/node@87af913b66eab78088acfd). libuv currently already provides translations for key events to control sequences, i.e. what this mode is intended to provide, but libuv does not and cannot translate all such events. Since the control sequences differ from the ones that Windows has chosen to standardize on, and applications may not be expecting this change, this is opt-in for now (but ideally will be the default behavior starting in libuv v2.x, should that ever happen). Another downside of this change is that not all shells reset this mode when an application exits. For example, when running a Node.js program with this flag enabled inside of PowerShell in Windows terminal, if the application exits while in raw TTY input mode, neither the shell nor the terminal emulator reset this flag, rendering the input stream unusable. While there's general awareness of the problem that console state is global state rather than per-process (same as on UNIX platforms), it seems that applications like PowerShell aren't expecting to need to unset this flag on the input stream, only its output counterpart (e.g. https://github.com/PowerShell/PowerShell/blob/4e7942135f998ab40fd3ae298b020e161a76d4ef/src/Microsoft.PowerShell.ConsoleHost/host/msh/ConsoleHost.cs#L1156). Hence, `uv_tty_reset_mode()` is extended to reset the terminal to its original state if the new mode is being used. Refs: nodejs/node@87af913 Refs: microsoft/terminal#4954
Notes:
We should investigate our options here: can we make the input or output mode process state?
If we make the input mode process-local, we need to move to an input model that miniksa and I have discussed: input records are translated (mouse -> vt, input -> vt, clipboard -> key, or clipboard -> vt) for the reader instead of upon insertion into the queue. That's a huge chunk of work.
Making the output mode process-local may have many fewer caveats. We already have some process-local output state like UTF-8 partials.
This'll solve the overarching issue in #4921 and #4949.
The text was updated successfully, but these errors were encountered: