Stop restoring tty modes when run non-interactively

fish reads the tty modes at startup, and tries to restore them to the
original values on exit, to be polite. However this causes problems when
fish is run in a pipeline with another process which also messes with the
tty modes. Example:

    fish -c 'echo foo' | vim -

Here vim's manipulation of the tty would race with fish, and often vim
would end up with broken modes.

Only restore the tty if we are interactive. Fixes #8705.
This commit is contained in:
ridiculousfish 2022-03-19 14:53:43 -07:00
parent df2cbe321c
commit 3e5284aaf2
3 changed files with 6 additions and 4 deletions

View File

@ -20,6 +20,7 @@ Scripting improvements
- ``read`` is now faster as the last process in a pipeline (:issue:`8552`).
- ``string join`` gained a new ``--no-empty`` flag to skip empty arguments (:issue:`8774`, :issue:`8351`).
- ``read`` now actually only triggers the ``fish_read`` event, not the ``fish_prompt`` event (:issue:`8797`). It was supposed to work this way since fish 3.2.0.
- The tty modes are no longer restored when non-interactive shells exit. This fixes wrong tty modes in pipelines with interactive commands. (:issue:`8705`).
Interactive improvements
------------------------

View File

@ -517,7 +517,7 @@ int main(int argc, char **argv) {
// If we have no config, we default to the default key bindings.
parser.vars().set_one(L"fish_key_bindings", ENV_UNEXPORT, L"fish_default_key_bindings");
if (function_exists(L"fish_default_key_bindings", parser)) {
std::vector<std::string> cmd {"fish_default_key_bindings"};
std::vector<std::string> cmd{"fish_default_key_bindings"};
run_command_list(parser, &cmd, {});
}
}

View File

@ -1416,10 +1416,11 @@ void reader_init() {
termsize_container_t::shared().updating(parser);
}
/// Restore the term mode if we own the terminal. It's important we do this before
/// restore_foreground_process_group, otherwise we won't think we own the terminal.
/// Restore the term mode if we own the terminal and are interactive (#8705).
/// It's important we do this before restore_foreground_process_group,
/// otherwise we won't think we own the terminal.
void restore_term_mode() {
if (getpgrp() != tcgetpgrp(STDIN_FILENO)) return;
if (!is_interactive_session() || getpgrp() != tcgetpgrp(STDIN_FILENO)) return;
if (tcsetattr(STDIN_FILENO, TCSANOW, &terminal_mode_on_startup) == -1 && errno == EIO) {
redirect_tty_output();