From 3951a858ddb57198369919285ccc2ebece14fbfe Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Wed, 28 May 2025 12:02:18 +0200 Subject: [PATCH] reader: do not send queries if stdout is not a terminal Interactive fish with output redirected ("fish >/dev/null") is not a common use case but it is valid. Perhaps surprisingly, "fish >some-file" *does* print terminal escape codes (colors, cursor movement etc.) even if terminal output is not a TTY. This is typically harmless, and potentially useful for debugging. We also send blocking terminal queries but those are not harmless in this case. Since no terminal will receive the queries, we hang; indefinitely as of today, but we should give up after a timeout and print an error. Either way that seems needlessly surprising. Suppress queries in this case. In future, we should probably do something similar if stdin is not a terminal; though in that case we're even less likely to be interactive (only "-i" I think). --- src/reader.rs | 9 ++++++++- tests/checks/tmux-invocation.fish | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/checks/tmux-invocation.fish diff --git a/src/reader.rs b/src/reader.rs index 5067ccbba..098323c43 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -243,7 +243,11 @@ pub(crate) fn initial_query( vars: Option<&dyn Environment>, ) { blocking_query.get_or_init(|| { - let query = if is_dumb() || IN_MIDNIGHT_COMMANDER.load() || IN_DVTM.load() { + let query = if is_dumb() + || IN_MIDNIGHT_COMMANDER.load() + || IN_DVTM.load() + || !isatty(STDOUT_FILENO) + { None } else { // Query for kitty keyboard protocol support. @@ -1525,6 +1529,9 @@ pub(crate) fn blocking_query(&self) -> RefMut<'_, Option> { } pub fn request_cursor_position(&mut self, out: &mut Outputter, q: CursorPositionQuery) { + if !isatty(STDOUT_FILENO) { + return; + } let mut query = self.blocking_query(); assert!(query.is_none()); *query = Some(TerminalQuery::CursorPositionReport(q)); diff --git a/tests/checks/tmux-invocation.fish b/tests/checks/tmux-invocation.fish new file mode 100644 index 000000000..01100371d --- /dev/null +++ b/tests/checks/tmux-invocation.fish @@ -0,0 +1,20 @@ +#RUN: %fish %s +#REQUIRES: command -v tmux + +set -g isolated_tmux_fish_extra_args -C ' + set -g fish (status fish-path) +' +isolated-tmux-start + +# Implicit interactive but output is redirected. +isolated-tmux send-keys \ + '$fish >output' Enter +tmux-sleep +isolated-tmux send-keys \ + 'status is-interactive && printf %s i n t e r a c t i v e \n' Enter \ + C-d +tmux-sleep +# Extract the line where command output starts. +string match