From fd4c1f891cd1efa318786fd5027d185528ffabd5 Mon Sep 17 00:00:00 2001 From: NoobZang Date: Tue, 25 Nov 2025 22:28:06 +0800 Subject: [PATCH] top: Fix refresh hangs by correctly configuring non-blocking TTY Setting O_NONBLOCK via fcntl is not sufficient for TTYs in non-canonical mode. A subsequent tcsetattr call would override this, as the default VMIN and VTIME settings cause the driver to block. Explicitly set VMIN and VTIME to 0 to ensure a true non-blocking read. Also, apply these TTY settings to STDIN_FILENO instead of STDOUT_FILENO. This is semantically more correct as we are configuring input behavior. Fixes #26166. --- Userland/Utilities/top.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Userland/Utilities/top.cpp b/Userland/Utilities/top.cpp index 66c67d6ded6023..ff0786c85ad12a 100644 --- a/Userland/Utilities/top.cpp +++ b/Userland/Utilities/top.cpp @@ -208,20 +208,22 @@ static ErrorOr setup_tty() { g_old_stdin_status_flags = TRY(Core::System::fcntl(STDIN_FILENO, F_GETFL)); TRY(Core::System::fcntl(STDIN_FILENO, F_SETFL, g_old_stdin_status_flags | O_NONBLOCK)); - g_previous_tty_settings = TRY(Core::System::tcgetattr(STDOUT_FILENO)); + g_previous_tty_settings = TRY(Core::System::tcgetattr(STDIN_FILENO)); struct termios raw = g_previous_tty_settings; raw.c_lflag &= ~(ECHO | ICANON); + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 0; // Disable echo and line buffering - TRY(Core::System::tcsetattr(STDOUT_FILENO, TCSAFLUSH, raw)); + TRY(Core::System::tcsetattr(STDIN_FILENO, TCSAFLUSH, raw)); return {}; } static void restore_tty() { - auto maybe_error = Core::System::tcsetattr(STDOUT_FILENO, TCSAFLUSH, g_previous_tty_settings); + auto maybe_error = Core::System::tcsetattr(STDIN_FILENO, TCSAFLUSH, g_previous_tty_settings); if (maybe_error.is_error()) warnln("Failed to reset original terminal state: {}", strerror(maybe_error.error().code()));