From 933c6900308fe321b8f7aa765df293969d81e399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 20 Nov 2025 14:27:57 +0100 Subject: [PATCH] basic/terminal-util: operate on one fd in terminal_get_size_by_dsr() This moves the open call earlier, so that we do any state-changing operations if we actually managed to open the nonblocking fd. This makes the code more robust because if the fdreopen call fails, we won't make modifications to the state of the terminal. --- src/basic/terminal-util.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index b7de72daed..f17352b41b 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -2369,7 +2369,6 @@ int terminal_get_size_by_dsr( unsigned *ret_rows, unsigned *ret_columns) { - _cleanup_close_ int nonblock_input_fd = -EBADF; int r; assert(input_fd >= 0); @@ -2397,14 +2396,20 @@ int terminal_get_size_by_dsr( if (r < 0) return log_debug_errno(r, "Called with distinct input/output fds: %m"); + /* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() + * should someone else process the POLLIN. Do all subsequent operations on the new fd. */ + _cleanup_close_ int nonblock_input_fd = r = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); + if (r < 0) + return r; + struct termios old_termios; - if (tcgetattr(input_fd, &old_termios) < 0) + if (tcgetattr(nonblock_input_fd, &old_termios) < 0) return log_debug_errno(errno, "Failed to get terminal settings: %m"); struct termios new_termios = old_termios; termios_disable_echo(&new_termios); - if (tcsetattr(input_fd, TCSANOW, &new_termios) < 0) + if (tcsetattr(nonblock_input_fd, TCSANOW, &new_termios) < 0) return log_debug_errno(errno, "Failed to set new terminal settings: %m"); unsigned saved_row = 0, saved_column = 0; @@ -2417,13 +2422,6 @@ int terminal_get_size_by_dsr( if (r < 0) goto finish; - /* Open a 2nd input fd, in non-blocking mode, so that we won't ever hang in read() should someone - * else process the POLLIN. */ - - nonblock_input_fd = r = fd_reopen(input_fd, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY); - if (r < 0) - goto finish; - usec_t end = usec_add(now(CLOCK_MONOTONIC), CONSOLE_REPLY_WAIT_USEC); char buf[STRLEN("\x1B[1;1R")]; /* The shortest valid reply possible */ size_t buf_full = 0; @@ -2516,7 +2514,7 @@ finish: if (saved_row > 0 && saved_column > 0) RET_GATHER(r, terminal_set_cursor_position(output_fd, saved_row, saved_column)); - RET_GATHER(r, RET_NERRNO(tcsetattr(input_fd, TCSANOW, &old_termios))); + RET_GATHER(r, RET_NERRNO(tcsetattr(nonblock_input_fd, TCSANOW, &old_termios))); return r; }